Compare commits

..

808 Commits

Author SHA1 Message Date
Max Kotliar
e9261be945 lib/promutil: Weak pointer based labels compressor 2025-08-20 20:02:11 +03:00
Andrii Chubatiuk
16a75129be docs: exclude files from rendering by hugo (#9591)
required for https://github.com/VictoriaMetrics/vmdocs/issues/164

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-08-20 12:04:06 +03:00
Nikolay
68bdb5e4d3 go.mod: unpin cloud.google.com/go/storage
Add build tag `disable_grpc_modules` for vmbackup, vmrestore and
vmbackupmanager. Binary size increases only for 3MB with it. It's
acceptable trade-off for security and feature updates.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8008
2025-08-19 12:21:54 +02:00
Fred Navruzov
4360d10962 docs/vmanomaly: release v1.25.3 (#9597)
### Describe Your Changes

Update docs to vmanomaly release v1.25.3

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-08-19 10:24:48 +04:00
Roman Khavronenko
ce9c868f59 benchmarks: update makefile commands
* check if built binary is present for `make tsbs-build`. Before, if
build fails, the command stopped working.
* make ENV variables configurable from command line, so `TSBS_STEP=15s
make tsbs-generate-data` would respect the configured step.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-08-18 22:47:16 +02:00
Arie Heinrich
212ce1baf0 Spelling and Markdown Standards
Another batch of documentation improvements

Fix Spelling in:
- Comments in code
- Displayed strings

One change was in a json file used for the anomaly dashboard in docker,
else no other code was changed.

Some Markdown changes, related to standards:
- URLs
- List numbering
- Empty spaces at the end of a line
2025-08-18 22:46:34 +02:00
Corporte Gadfly
1a091e5831 fix typo in sentence 2025-08-18 22:41:47 +02:00
Zakhar Bessarab
bac186fc65 deployment: update image tags to the latest release
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-08-18 16:08:35 +04:00
Zakhar Bessarab
15ce9e5e49 docs: update references to the latest releases
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-08-18 16:08:12 +04:00
Zakhar Bessarab
2c1596ea84 docs/changelog: backport LTS release notes
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-08-18 15:36:43 +04:00
f41gh7
21d4f844ab synctest: replace deprecated Run call with Test
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-08-17 21:00:17 +02:00
f41gh7
da0002ce66 Makefile: upgrade golangci-lint from 2.2.1 to 2.4.0
Changelog https://golangci-lint.run/docs/product/changelog/#240
2025-08-17 20:36:14 +02:00
f41gh7
f35b9ed36d deployment/docker: update Go builder from 1.24.6 to 1.25.0
Changes https://tip.golang.org/doc/go1.25
2025-08-17 20:31:30 +02:00
Zakhar Bessarab
b4dc67cba6 docs/CHANGELOG.md: cut v1.124.0
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-08-15 15:00:46 +04:00
Zakhar Bessarab
70afdd0285 docs: update version tooltips
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-08-15 14:51:10 +04:00
Zakhar Bessarab
51efd2c32b app/vmselect: run make vmui-update
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-08-15 14:46:49 +04:00
Max Kotliar
1e208a8c79 .github: add copilot instruction (#9586)
### Describe Your Changes

Trying to teach Copilot correct changelog changes, such as a misplaced
entry
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9306#issuecomment-3185126897

I couldn’t test this properly because Copilot doesn’t pick up
instructions from the PR itself. They must be on the master branch. The
instruction needs to be merged first, then tested. Please review.

If it doesn’t work, I’ll remove it.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-08-14 19:50:55 +03:00
Andrei Baidarov
e49027df8f app/vmagent: properly apply dropOnOverload condition
Previously, vmagent treated differently the following configuration:

1) ./bin/vmagent --remoteWrite.url=url-0 --remoteWrite.url=url-1 --remoteWrite.disableOndiskQueue

 and

2)./bin/vmagent --remoteWrite.url=url-0 --remoteWrite.url=url-1 --remoteWrite.disableOndiskQueue=true,true

In first case, it could produce duplicates and blocks ingestion requests if one of remote write targets were not accessible.
In second case, it implicitly added --remoteWrite.dropSamplesOnOverload as true and silently dropped samples for inaccessible target.

 This commit treat this configuration as the same and silently drop samples on both cases to mitigate possible duplicates. 

 It's expected, that vmagent provides delivery guarantees, only if it has a single remote write target, when flag remoteWrite.disableOndiskQueue=true is set.


Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9565
2025-08-14 16:11:08 +02:00
Andrii Chubatiuk
a518a4a904 lib/backup: added checksum algorithm for all S3 PutObject requests (#9549)
fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9532
set checksum algorithm to SHA256, not sure if this property should be
configurable

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
Co-authored-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-08-14 17:50:03 +04:00
Artem Fetishev
ad46fce7d4 lib/storage: fix searchMetricName() (#9582)
While working on #9431 there has been introduced 2 bugs related to
indexDB.searchMetricName():

1. During the search the index records are unconditionally placed in
sparse index
2. If search touches index records in both prev and curr indexDBs, there
will be possible cases that metricIDs can be unintentionally removed
using `wasMetricIDMissingBefore()` logic

Additionally, the PR moves the searchMetricName from indexDB and Search
to Storage which simplifies the code and makes it spossible to reuse the
function as-is in enterprise code.

Follow up for #9431.

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-08-14 10:10:21 +02:00
Max Kotliar
7cc13ee1cc docs/changelog: move metadata changelog record to tip
Follow up on
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9306
2025-08-13 21:58:49 +03:00
dependabot[bot]
74fcd10d2e build(deps): bump actions/checkout from 4 to 5 (#9574)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to
5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/releases">actions/checkout's
releases</a>.</em></p>
<blockquote>
<h2>v5.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update actions checkout to use node 24 by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li>
<li>Prepare v5.0.0 release by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2238">actions/checkout#2238</a></li>
</ul>
<h2>⚠️ Minimum Compatible Runner Version</h2>
<p><strong>v2.327.1</strong><br />
<a
href="https://github.com/actions/runner/releases/tag/v2.327.1">Release
Notes</a></p>
<p>Make sure your runner is updated to this version or newer to use this
release.</p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v4...v5.0.0">https://github.com/actions/checkout/compare/v4...v5.0.0</a></p>
<h2>v4.3.0</h2>
<h2>What's Changed</h2>
<ul>
<li>docs: update README.md by <a
href="https://github.com/motss"><code>@​motss</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
<li>Add internal repos for checking out multiple repositories by <a
href="https://github.com/mouismail"><code>@​mouismail</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
<li>Documentation update - add recommended permissions to Readme by <a
href="https://github.com/benwells"><code>@​benwells</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
<li>Adjust positioning of user email note and permissions heading by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2044">actions/checkout#2044</a></li>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li>
<li>Update CODEOWNERS for actions by <a
href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2224">actions/checkout#2224</a></li>
<li>Update package dependencies by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li>
<li>Prepare release v4.3.0 by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2237">actions/checkout#2237</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/motss"><code>@​motss</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
<li><a href="https://github.com/mouismail"><code>@​mouismail</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
<li><a href="https://github.com/benwells"><code>@​benwells</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
<li><a href="https://github.com/nebuk89"><code>@​nebuk89</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li>
<li><a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v4...v4.3.0">https://github.com/actions/checkout/compare/v4...v4.3.0</a></p>
<h2>v4.2.2</h2>
<h2>What's Changed</h2>
<ul>
<li><code>url-helper.ts</code> now leverages well-known environment
variables by <a href="https://github.com/jww3"><code>@​jww3</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/1941">actions/checkout#1941</a></li>
<li>Expand unit test coverage for <code>isGhes</code> by <a
href="https://github.com/jww3"><code>@​jww3</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1946">actions/checkout#1946</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v4.2.1...v4.2.2">https://github.com/actions/checkout/compare/v4.2.1...v4.2.2</a></p>
<h2>v4.2.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Check out other refs/* by commit if provided, fall back to ref by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1924">actions/checkout#1924</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Jcambass"><code>@​Jcambass</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/1919">actions/checkout#1919</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v4.2.0...v4.2.1">https://github.com/actions/checkout/compare/v4.2.0...v4.2.1</a></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h2>V5.0.0</h2>
<ul>
<li>Update actions checkout to use node 24 by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li>
</ul>
<h2>V4.3.0</h2>
<ul>
<li>docs: update README.md by <a
href="https://github.com/motss"><code>@​motss</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
<li>Add internal repos for checking out multiple repositories by <a
href="https://github.com/mouismail"><code>@​mouismail</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
<li>Documentation update - add recommended permissions to Readme by <a
href="https://github.com/benwells"><code>@​benwells</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
<li>Adjust positioning of user email note and permissions heading by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2044">actions/checkout#2044</a></li>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li>
<li>Update CODEOWNERS for actions by <a
href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2224">actions/checkout#2224</a></li>
<li>Update package dependencies by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li>
</ul>
<h2>v4.2.2</h2>
<ul>
<li><code>url-helper.ts</code> now leverages well-known environment
variables by <a href="https://github.com/jww3"><code>@​jww3</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/1941">actions/checkout#1941</a></li>
<li>Expand unit test coverage for <code>isGhes</code> by <a
href="https://github.com/jww3"><code>@​jww3</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1946">actions/checkout#1946</a></li>
</ul>
<h2>v4.2.1</h2>
<ul>
<li>Check out other refs/* by commit if provided, fall back to ref by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1924">actions/checkout#1924</a></li>
</ul>
<h2>v4.2.0</h2>
<ul>
<li>Add Ref and Commit outputs by <a
href="https://github.com/lucacome"><code>@​lucacome</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1180">actions/checkout#1180</a></li>
<li>Dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>- <a
href="https://redirect.github.com/actions/checkout/pull/1777">actions/checkout#1777</a>,
<a
href="https://redirect.github.com/actions/checkout/pull/1872">actions/checkout#1872</a></li>
</ul>
<h2>v4.1.7</h2>
<ul>
<li>Bump the minor-npm-dependencies group across 1 directory with 4
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1739">actions/checkout#1739</a></li>
<li>Bump actions/checkout from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1697">actions/checkout#1697</a></li>
<li>Check out other refs/* by commit by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1774">actions/checkout#1774</a></li>
<li>Pin actions/checkout's own workflows to a known, good, stable
version. by <a href="https://github.com/jww3"><code>@​jww3</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1776">actions/checkout#1776</a></li>
</ul>
<h2>v4.1.6</h2>
<ul>
<li>Check platform to set archive extension appropriately by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1732">actions/checkout#1732</a></li>
</ul>
<h2>v4.1.5</h2>
<ul>
<li>Update NPM dependencies by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1703">actions/checkout#1703</a></li>
<li>Bump github/codeql-action from 2 to 3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1694">actions/checkout#1694</a></li>
<li>Bump actions/setup-node from 1 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1696">actions/checkout#1696</a></li>
<li>Bump actions/upload-artifact from 2 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1695">actions/checkout#1695</a></li>
<li>README: Suggest <code>user.email</code> to be
<code>41898282+github-actions[bot]@users.noreply.github.com</code> by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1707">actions/checkout#1707</a></li>
</ul>
<h2>v4.1.4</h2>
<ul>
<li>Disable <code>extensions.worktreeConfig</code> when disabling
<code>sparse-checkout</code> by <a
href="https://github.com/jww3"><code>@​jww3</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1692">actions/checkout#1692</a></li>
<li>Add dependabot config by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1688">actions/checkout#1688</a></li>
<li>Bump the minor-actions-dependencies group with 2 updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1693">actions/checkout#1693</a></li>
<li>Bump word-wrap from 1.2.3 to 1.2.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1643">actions/checkout#1643</a></li>
</ul>
<h2>v4.1.3</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="08c6903cd8"><code>08c6903</code></a>
Prepare v5.0.0 release (<a
href="https://redirect.github.com/actions/checkout/issues/2238">#2238</a>)</li>
<li><a
href="9f265659d3"><code>9f26565</code></a>
Update actions checkout to use node 24 (<a
href="https://redirect.github.com/actions/checkout/issues/2226">#2226</a>)</li>
<li>See full diff in <a
href="https://github.com/actions/checkout/compare/v4...v5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4&new-version=5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-13 19:01:59 +03:00
Zakhar Bessarab
59007cda51 docs: update examples to use proper license flags (#9579)
`-eula` was deprecated and made no-op in v1.123.0, so examples with
`-eula` will no longer work.
Replace those with proper license configuration.

While at it, remove license flags from vmbackupmanager CLI commands as
it is not required when using CLI.

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-08-13 19:12:19 +04:00
hagen1778
5869a39e7b metricsql: return a proper error message for scalar arguments
Follow-up for 8b92af9d45

Initial PR contained the change for getScalar function - see https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9548
But change was dropped during incorrect rebase.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-08-13 13:22:13 +02:00
Max Kotliar
c3c802a61c apptest: Fix flaky TestSingleVMAuthRouterWithAuth (#9575)
### Describe Your Changes

Do not check vmauth_config_last_reload_success_timestamp_seconds since
it may contain the timestamp < time.Now() due to how lib/fasttime works.

Instead, compare the number of config reloads.

follow up on
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9369 and
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9572

Also, split the config update and reload into two separate functions. 

master:
```
$gotest -race ./apptest/tests/ -run=TestSingleVMAuthRouterWithInternalAddr -count=40
ok  	github.com/VictoriaMetrics/VictoriaMetrics/apptest/tests	90.176s
```

pr:
```
$gotest -race ./apptest/tests/ -run=TestSingleVMAuthRouterWithInternalAddr -count=40
ok  	github.com/VictoriaMetrics/VictoriaMetrics/apptest/tests	46.130s
```

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-08-13 13:05:15 +02:00
Hui Wang
8b92af9d45 metricsql: return a proper error message when the function argument i… (#9548)
…s expected to be a string

In MetricsQL, functions like
[count_values](https://docs.victoriametrics.com/victoriametrics/metricsql/#count_values),
[label_replace](https://docs.victoriametrics.com/victoriametrics/metricsql/#label_replace)
expect string arguments, and `getString()` checks if the result from a
string expr query.
Previously, error messages were not intuitive, now
`label_replace("","","","",up)` and `label_replace("","","","",1)`
should return clearer error message.
2025-08-13 13:05:00 +02:00
Hui Wang
e313874d01 vmalert: fix the {{ $activeAt }} variable value in annotation templ… (#9576)
…ating when the alert has already triggered

fix https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9543, 
bug was introduced in
[v1.101.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.101.0)
with
a84491324d.
2025-08-13 12:59:00 +02:00
Hui Wang
58a4e48901 vmalert: fix potential data race and missing firing states when repla… (#9559)
…ying alerting rule with `-replay.ruleEvaluationConcurrency>1`
2025-08-13 12:56:27 +02:00
Andrei Baidarov
16d75ab0bd lib/storage: remove extDB from indexDB, search indexDBs independently (#9431)
Removing extDB from indexDB makes prev, curr, and next indexDBs independent.
I.e. the search is performed independently in prev and curr, the results are
then merged.
    
Additionally, since no search is now performed in extDB:
- all indexDB search methods now return the original maps used for populating
  the result, without invermediate conversion to slices.
 - `NoExtDB` suffix has been removed from method names
  
This has been extracted from #8134.
    
Signed-off-by: Andrei Baidarov <baidarov@nebius.com>
Co-authored-by: Artem Fetishev <rtm@victoriametrics.com>
2025-08-13 07:36:09 +02:00
Dmytro Kozlov
fe0afc3fea benchmark: update date calculation for the benchmark script (#9563)
### Describe Your Changes

Updated date calculation for the TSBS benchmark. Before it requires the
installation of the `coreutils` if you run those benchmarks on the macOS
system, but you do not need to install anything.
`make tsbs` should work correctly on Linux and macOS as well.

Checked on both systems, it works correctly:
1. MacOS 
<img width="1292" height="372" alt="Screenshot 2025-08-08 at 11 45 03"
src="https://github.com/user-attachments/assets/609a797d-c54a-40d3-abe2-270c173ff9c3"
/>

2. Linux
<img width="1440" height="283" alt="Screenshot 2025-08-08 at 11 46 33"
src="https://github.com/user-attachments/assets/e9f094a1-40cc-4cd2-afd5-55c5678c041f"
/>

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-08-12 16:43:24 +02:00
Roman Khavronenko
f99e49c15d dashboards/victoriametrics-cluster: show max 99th percentile on vmselect panels (#9555)
Before, we showed summarized 99th percentile for query complexity across
all available instance. This doesn't make much sense, as it doesn't
answer on the following questions:
1. What complexity limits to set per vmselect
2. What are the most expensive queries

The change is to use `max` instead of `sum`, to show only outliers, the
heaviest served queries. The update should help answering on questions
above.

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-08-12 16:43:07 +02:00
Andrii Chubatiuk
1ba994970b metricsql: fixed gaps in histogram_quantile calculation, when first bucket contains NaNs (#9547)
fixes case, when `histogram_quantile` result contains gaps, that occur
in same time range, where NaNs are present in a first bucket of a
histogram

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-08-12 16:41:58 +02:00
Hui Wang
25cd5637bc app/vmagent: add time series metadata support
By default, `vmagent` doesn't parse
[metadata](https://github.com/prometheus/docs/blob/main/docs/instrumenting/exposition_formats.md)
when scraping targets, and drops metadata that received via [Prometheus remote write v1(https://prometheus.io/docs/specs/prw/remote_write_spec/) or
[OpenTelemetryprotocol](https://github.com/open-telemetry/opentelemetryproto/blob/v1.7.0/opentelemetry/proto/metrics/v1/metrics.proto).

To enable parsing metadata when scraping and sending metadata to the
configured `-remoteWrite.url`, set `-enableMetadata=true`.

Besides native metadata fields, vmagent also adds tenant info to
metadata when `-enableMultitenantHandlers` is enabled and data is sent
via the multitenant endpoints (/insert/<accountID>/<suffix>), allowing
storing metadata under different tenants in VictoriaMetrics cluster.
However, if `vm_account_id` or `vm_project_id labels` are added directly
in metrics labels and send to the [vminsert multitenantendpoints](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/#multitenancy-via-labels),
tenant info won't be attached in the metadata, and it will be stored in
the default tenant of VictoriaMetrics cluster.

part of https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2974
2025-08-12 15:19:50 +02:00
Max Kotliar
00c7533095 apptest: fix flaky single vmauth router with auth test
Fix flaky integration test `TestSingleVMAuthRouterWithAuth`.
The flakiness is caused by the
`vmauth_config_last_reload_success_timestamp_seconds` metric, which
reports time with second-level precision.
Update the test to account for this when verifying that the config
reloads correctly.
2025-08-12 11:35:58 +02:00
Nikolay
f668e5d9c6 lib/storage: cardinality limiter prevent performance degradation on limit hit
Previously, if limit was reached for cardinality limiter, vmstorage
started to perform index lookups for any series exceed limit. Since
storage must skip index creation for such series, it's not possible to
cache it. It resulted into opposite effect of cardinality limiter -
instead of reducing resource usage, it increased it instead.

 This commit changes cardinality limit calculation from metricID to the
hash from raw metricName. It could slightly increase CPU usage if
cardinality limiter is configured, since hash must be calculated for
each metricName row. But it mitigates excessive CPU and memory usage on
limit hit

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9554
2025-08-12 11:32:31 +02:00
Nikolay
f4548a46a7 docs: add vmselect group and vmstorage node auto-discovery 2025-08-12 11:31:48 +02:00
Max Kotliar
7048de8d20 docs: add available from hint for -rpc.handshakeTimeout flag
follow up on
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9541
2025-08-12 10:12:02 +03:00
Max Kotliar
cba4b2f0df lib/handshake: set deadline for whole handshake; change deadline (1s per op to 3s whole process) (#9541)
The current one-second timeout for individual read or write operations
during the handshake phase has proven to be insufficient in some
scenarios
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9345. For
example, short-lived CPU spikes lasting a few seconds can cause
handshake failures due to the low timeout threshold.

While a small timeout may work well in environments with fast and
reliable networking, such as within a single datacenter, it becomes
problematic in more complex setups—particularly in a [multi-level
cluster
setup](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/#multi-level-cluster-setup)
where the top-level vmselect may reside in a different availability zone
and work on a less reliable network.

Another issue with the per-operation timeout approach is that it allows
the total time for a handshake to accumulate significantly in the
worst-case scenario. If each operation experiences a delay just under
the timeout threshold, the entire handshake process could take up to 6s.
Which accounts for 60% of `-search.maxQueueDuration` and leaves only 4s
for the actual query.

Introducing a single timeout for the entire handshake process would
provide more predictable behavior and improve usability from a
configuration standpoint. The timeout for the whole handshake op is also
easier to understand from the operator's point of view. Increasing the
timeout value and providing a configuration option for it would make the
system more resilient to transient conditions like CPU contention and
better suited for use cases involving cross-AZ communication.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9345

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-08-11 19:35:55 +03:00
Max Kotliar
068d5a4b07 .github/workflows: Run cross builds and tests in parallel (#9443)
### Describe Your Changes

The commit changes CI behavior:
- Run build in parallel for different os\arch
- Run unit\integration\lint in parallel
- Remove the custom Go cache step in favor of the logic provided in
`actions/setup-go`. The custom cache was used to build key based on
go.sum and makefiles. This logic is preserved.
- Introduce cache for golangci-lint. 

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-08-11 15:55:36 +03:00
Max Kotliar
e392cbbba3 apptest: Add vmauth use proxy protocol integration test (#9556)
### Describe Your Changes

Add an integration test that verifies that vmauth works with
`-httpListenAddr.useProxyProtocol=true` enabled and the x-forwarded-for
header is propagated correctly.

Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9546

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-08-11 15:49:38 +03:00
Aliaksandr Valialkin
06f590ee63 lib/envtemplate: allow referring non-existing environment variables in config files and in command-line flags
A few users reported unexpected errors when environment variables referred other environment variables
at VictoriaMetrics startup. This resulted in the following fatal error on startup:

    cannot expand "..." env var value "...%{SOME_NON_EXISTING_ENV_VAR}..."

Fix this by leaving placeholders with non-existing env vars as is.
This improves the general usability of environment variables by VictoriaMetrics components
inside command-line flags and inside config files. User can easily notice placeholders with non-existing
environment variables by looking at the corresponding command-line flag or at the corresponding config option value.

While at it, replace duplicate docs about environment variables at the https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/#environment-variables
with the link to the same docs at https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#environment-variables .

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3999
2025-08-09 21:05:13 +02:00
Aliaksandr Valialkin
5eef1d66e0 go.sum: run go mod tidy after 1f2c14260c 2025-08-08 20:23:57 +02:00
Aliaksandr Valialkin
5a572387cf deployment/docker: update Go builder from Go1.24.5 to Go1.24.6
See https://github.com/golang/go/issues?q=milestone%3AGo1.24.6+label%3ACherryPickApproved
2025-08-08 20:21:57 +02:00
Charles-Antoine Mathieu
c6b165ecba app/vmselect: truncate graphite excessive pathExpression field
vmselect is experiencing memory exhaustion and OOM kills
when processing complex Graphite queries with nested functions and large
numbers of label selectors (30k+ values).

The root cause was unbounded growth of the pathExpression field.

 This commit adds configurable truncation for Graphite pathExpression fields to
prevent memory exhaustion while preserving query functionality:

New flag: -search.maxGraphitePathExpressionLen=1024 (default 1024
characters)
Safe truncation: Long expressions are truncated with "..." suffix
Zero disables: Set to 0 to disable truncation entirely

Related PR https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9534/
2025-08-08 13:44:29 +02:00
Max Kotliar
fd928a0f5b lib/netutil: fix linter issues in proxy protocol tests 2025-08-07 14:35:35 +03:00
Nikolay
c207c32c44 lib/netutil: properly accept proxy protocol
Previously, tcp listener perform synchronous proxy protocol header
read during connection accept. It could significantly reduce vmauth
performance and lead to timeout at serving http requests.

 This commit changes this logic and performs proxy protocol header
parsing during first Read request from connection or RemoteAddr method
call. It significantly improves performance and reduce possible
bottleneck at connections accept method.

Related PR https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9546/
2025-08-07 12:25:35 +02:00
f41gh7
1f2c14260c go.mod: update fastcache to v1.13.0 2025-08-06 18:29:05 +02:00
Max Kotliar
87604e6df6 lib/prompb: fix review comment after merge prompbmarshal into prompn
- Rename WriteRequestUnmarshaller to WriteRequestUnmarshaler
- Add a description to WriteRequestUnmarshaler struct

Review comments
b98e592752 (r163365472)

Follow up on
b98e592752
2025-08-06 19:23:50 +03:00
Alexander Frolov
1beb1f69d5 vmselect: properly release tmp blocks for /federate
The `/federate` endpoint handler might return early before calling
`rss.RunParallel()`, which causes temporary block files to not be closed
properly.

Related PR: https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9536
2025-08-06 18:20:06 +02:00
Andrii Chubatiuk
5266bf1f3b docs: override canonical url of pages, that have multiple copies (#9550)
### Describe Your Changes

multiple pages, that reference same document in `{% content %}`
shortcode same content, but different canonical URLs, added canonical
parameter to override default url

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-08-06 16:13:20 +02:00
Roman Khavronenko
d4aefcecc4 docs: mention series of articles on VM internals in FAQ (#9528)
While there, mention https://victoriametrics.com/blog in the articles
section, as it seems not being mentioned anywhere.

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: Mathias Palmersheim <mathias@victoriametrics.com>
2025-08-06 16:11:10 +02:00
Zakhar Bessarab
93c373d55a dashboards/vmagent: fix expression for samples rate (#9530)
In case vmagent does not scrape any metrics left part will be evaluated
as empty resulting in right part being skipped.

Before:
<details>
<img width="1401" height="1080" alt="image"
src="https://github.com/user-attachments/assets/c242593f-8503-4bd2-b6a7-85c1dcc54d0f"
/>
</details> 

After:
<details>
<img width="1416" height="1128" alt="image"
src="https://github.com/user-attachments/assets/45565c28-a731-4f5d-af54-1ab3daf75778"
/>
</details>

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-08-06 16:08:02 +02:00
Hui Wang
58bc05ce56 vmalert-tool: fix panic when rule execution fails (#9540)
fix https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9526, 
bug was introduced from **v1.114.0**.

Please note, the rule execution failure should only happen if there is a
bad template or duplicated alert(rare case), added a test case to cover
the template.

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-08-06 16:02:22 +02:00
Roman Khavronenko
516a454f0a docs: update monitoring section (#9538)
* remove duplicated content between single and cluster versions
* mention recommendation to group component types by jobs in scrape
config
* link the example of scrape configs
* update wording

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-08-06 16:00:25 +02:00
Jamie Wiebe
9fd9de7ab4 vmui: fix typo in "returned too many series" message (#9533)
A few simple grammar changes on messages presented to the user
2025-08-06 16:00:12 +02:00
Max Kotliar
5a75b93535 docs/changelog: remove mention of latest Docker tag deprecation, clarify stable tag removal 2025-08-05 18:48:18 +03:00
f41gh7
787bf8ffed docs/cluster: follow-up after 33392e1135
Mention new logNewSeriesAuthKey flag at docs
2025-08-04 17:09:11 +02:00
f41gh7
f4bbb83b6a docs/changelog: add v1.110.15 and v1.122.1 changes
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-08-04 17:07:28 +02:00
f41gh7
b0409910dc docs: update LTS releases versions
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-08-04 17:05:25 +02:00
f41gh7
b421f43532 docs: mention v1.123.0 release at examples
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-08-04 17:04:21 +02:00
Aliaksandr Valialkin
847398b356 lib/fs/fs.go: added missing lock for the diskSpaceMapLock inside MustGetTotalSpace() function
This is a follow-up for 7da45924e2

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9523
Updates https://github.com/VictoriaMetrics/VictoriaLogs/issues/513
2025-08-04 10:12:14 +02:00
Aliaksandr Valialkin
53d8e99987 app/vmstorage: expose vm_total_disk_space_bytes metric, which shows disk volume size for -storageDataPath directory
This metric can be used for building alerts and graphs for free disk space usage percentage by using the following MetricsQL query:

    100 * (vm_free_disk_space_bytes / vm_total_disk_space_bytes)
2025-08-04 10:05:45 +02:00
Phuong Le
7da45924e2 lib/fs: Add total disk space retrieval (#9523)
Extends the disk space monitoring functionality by adding support for
retrieving total disk capacity in addition to free space.

Related: https://github.com/VictoriaMetrics/VictoriaLogs/issues/513

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-04 09:58:19 +02:00
Aliaksandr Valialkin
ddadfd6d58 vendor: run make vendor-update 2025-08-03 22:10:54 +02:00
Aliaksandr Valialkin
c025993e8a vendor: update github.com/VictoriaMetrics/metrics from v1.38.0 to v1.39.1 2025-08-03 22:06:19 +02:00
f41gh7
fbe5ddcc2b CHANGELOG.md: cut v1.123.0 release 2025-08-01 14:54:19 +02:00
f41gh7
6607711f45 make vmui-update 2025-08-01 14:42:56 +02:00
Zakhar Bessarab
8f6b7c2e8c apptest/tests: only flush component logs on test failure (#9491)
Update tests to only print component output in integration tests if the
test case is failing.

An example of pipeline failure:
https://github.com/VictoriaMetrics/VictoriaMetrics/actions/runs/16473633711/job/46569913168?pr=9491

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-08-01 14:21:14 +02:00
Aliaksandr Valialkin
c1cde61f20 docs/victoriametrics/changelog/CHANGELOG_2024.md: typo fix: steaming -> streaming
This is a follow-up for 8a7045e206
2025-08-01 13:33:46 +02:00
hagen1778
b8e82eef72 docs: fix copy&paste typo in stream aggregation
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-08-01 09:19:36 +02:00
Alexander Frolov
d0045ba51d lib/encoding/zstd: use sync stream decoder (purego) (#9518)
### Describe Your Changes

By default `zstd.Reader` creates multiple goroutines to process a single
connection:
- It doesn't match cgo behavior, which works synchronously, and creates
a lot more concurrent goroutines (0.5k -> 5k on my workload)
- It results in non-zero `vm_tcpdialer_errors_total{type="read"}` errors
on vmselect because an underlying connection is closed while a goroutine
is still reading from it. The goroutine created by
`zstd.NewReader`/`zstd.Reset`

abb348e4db/lib/handshake/buffered_conn.go (L113-L120)
- vmselect (and vmagent) doesn't benefit from async mode since it has
multiple readers in-use at the same time, which usually exceeds the
number of cpu cores

Partly related to #9218

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-31 20:40:17 +03:00
Dima Shur
8a7045e206 Fixed typo (#9524)
### Describe Your Changes

Fixed typo (steaming aggregation -> streaming aggregation)
Updated vmalert doc - there were counterintuitive links, made it clearer

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-31 17:52:00 +03:00
leiwingqueen
33392e1135 app/vmstorage: introduce /internal/log_new_series API
This commit introduces new storage API: `/internal/log_new_series`.
It helps to dynamically debug newly created series. Changing `-logNewSeries` value requires storage restart,
which may introduce downtime and is not recommended for production deployments.

 In addition, this commit adds flags: `-logNewSeriesAuthKey`, which protects newly added API.

Fixes: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8879
2025-07-31 13:07:44 +02:00
Aliaksandr Valialkin
656bcb23d3 docs/victoriametrics/Articles.md: add https://itnext.io/kubernetes-monitoring-a-complete-solution-part-1-architecture-eb5b998658d5 2025-07-31 11:56:03 +02:00
Aliaksandr Valialkin
c582b3a485 docs/victoriametrics/Articles.md: add https://medium.com/@isasamor/optimizing-datadog-costs-with-victoriametrics-a-practical-step-by-step-guide-c984d32c7423 2025-07-31 11:32:56 +02:00
Aliaksandr Valialkin
b2d8fc4b97 docs/victoriametrics/Articles.md: add https://medium.com/@heliodevhub/construindo-uma-stack-de-monitoramento-escal%C3%A1vel-e-econ%C3%B4mica-na-aws-com-victoria-metrics-532d535dcfb6 2025-07-31 11:31:39 +02:00
Aliaksandr Valialkin
7c3679075e docs/victoriametrics/Articles.md: add https://davidhernandez21.github.io/posts/Victoriametrics-k8s-stack-gotchas/ 2025-07-31 10:54:05 +02:00
dstevensson
7dd9407b94 lib/promscrape/discovery/gce: add support for ipv6 in metadata labels
This change will expose any IPv6 addresses assigned to an instance under
the meta labels:
* `__meta_gce_public_ipv6` -native IPv6 address, globally routed
* `__meta_gce_internal_ipv6` - unique local address (ULA).

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9370
2025-07-31 09:31:33 +02:00
Yury Molodov
59486f0bc1 vmui: always show tenant selector if tenant list is not empty
Previously, the tenant selector was hidden when only one tenant
was returned, making it impossible to run queries in multi-tenant mode.
Now, the selector is always shown as long as at least one tenant exists.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9396
2025-07-31 09:20:53 +02:00
Artem Fetishev
1229ed230d lib/storage: remove prefetching metric names as it does not improve performance anyway
Benchmark results:

Machine Type | Benchmark Log | Brief Conclusion
---------------------| ----------------------- |
------------------------
`GCP e2-standard-8 (AMD)` |
[e2-standard-8-no-prefetch-metric-names.log](https://github.com/user-attachments/files/21481629/e2-standard-8-no-prefetch-metric-names.log)
| slight degradation < 5%
`GCP n2-standard-8 (Intel)` |
[n2-standard-8-no-prefetch-metric-names.log](https://github.com/user-attachments/files/21481631/n2-standard-8-no-prefetch-metric-names.log)
| slight improvement < 5%
`GCP n2d-standard-8 (AMD)` |
[n2d-standard-8-no-prefetch-metric-names.log](https://github.com/user-attachments/files/21481630/n2d-standard-8-no-prefetch-metric-names.log)
| slight improvement < 5%, slight degradation < 5%



Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9137
---------

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-31 09:19:44 +02:00
Nikolay
98659633cc app/vmauth: properly set useProxyProtocol for httpInternalListenAddr
Commit e77df5d00b introduced
unintentional change, which prevents from using httpInternalListenAddr.
Which is designed to use with clients that do not support proxy
protocol.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9515
2025-07-31 09:18:24 +02:00
Fred Navruzov
676e22b65c docs/vmanomaly: v1.25.2 update
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9520
2025-07-31 09:18:00 +02:00
Max Kotliar
b98e592752 lib/prompb: Merge prompbmarshal logic into prompb
The prompb and prompbmarshal share exactly the same models and provide
marshal and unmarshale capabilities for them. This creates duplication
(changes in one model has to be made in another, case with metadata) and
confusion where for example you compare same looking models but golang
says they are not the same (because of the type).

This commit merge prompbmarshal logic into prompb so the rest of the
code is aligned on prompb models.

Moves samplesPool and labelsPool to WriteRequestUnmarshaller.
Make WriteRequest struct clean from unmarshal logic.

The benchmark shows no significant changes:

$benchstat prompbmarshal.bench prompb2.bench
goos: darwin
goarch: arm64
pkg: github.com/VictoriaMetrics/VictoriaMetrics/lib/prompb
cpu: Apple M1 Pro
                                 │ prompbmarshal.bench │           prompb2.bench            │
                                 │       sec/op        │   sec/op     vs base               │
WriteRequestUnmarshalProtobuf-10           189.2µ ± 5%   190.8µ ± 8%       ~ (p=0.579 n=10)
WriteRequestMarshalProtobuf-10             145.3µ ± 7%   143.6µ ± 2%       ~ (p=0.143 n=10)
geomean                                    165.8µ        165.5µ       -0.14%

                                 │ prompbmarshal.bench │            prompb2.bench            │
                                 │         B/s         │     B/s       vs base               │
WriteRequestUnmarshalProtobuf-10          50.42Mi ± 5%   49.99Mi ± 8%       ~ (p=0.593 n=10)
WriteRequestMarshalProtobuf-10            65.64Mi ± 7%   66.39Mi ± 2%       ~ (p=0.143 n=10)
geomean                                   57.53Mi        57.61Mi       +0.14%

                                 │ prompbmarshal.bench │            prompb2.bench             │
                                 │        B/op         │     B/op       vs base               │
WriteRequestUnmarshalProtobuf-10         27.70Ki ±  4%   26.90Ki ±  7%       ~ (p=0.190 n=10)
WriteRequestMarshalProtobuf-10           3.267Ki ± 12%   3.273Ki ± 12%       ~ (p=0.971 n=10)
geomean                                  9.514Ki         9.383Ki        -1.38%

                                 │ prompbmarshal.bench │            prompb2.bench            │
                                 │      allocs/op      │ allocs/op   vs base                 │
WriteRequestUnmarshalProtobuf-10          0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
WriteRequestMarshalProtobuf-10            0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=10) ¹
geomean                                              ²               +0.00%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean
2025-07-31 01:04:11 +03:00
Ivan Dudin
2f4cc0b699 docs: fix sentence duplication in "ascent_over_time" description (#9506)
### Describe Your Changes

Fixed sentence duplication in MetricsQL function description

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-30 19:41:38 +03:00
Max Kotliar
9c80b54df3 docs: upd changelog message for idbPrefillStart flag
follow up on
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9461
2025-07-30 19:37:55 +03:00
Max Kotliar
229ba50c8f docs: upd changelog message for idbPrefillStart flag
follow up on
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9461
2025-07-30 19:35:38 +03:00
Max Kotliar
b1321e0294 docs: fix link in changelog
introduced in
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9461
2025-07-30 19:28:59 +03:00
Nikolay
752723198c lib/storage: make indexDB prefill variable configurable (#9461)
This commit introduces new flag: `-storage.idbPrefillStart` with
default value of `1h`. It allows to adjust start time of the prefill
process for the data written into the next indexDB.

By default, VictoriaMetrics starts prefill indexDB at 3 A.M UTC, while
indexDB rotates at 4 A.M UTC. It could be useful to change start time
from 3 A.M. to 1 A.M or 00:00 A.M. It should smooth overall resource
usage.

However, changing value to the number bigger than 4 hours for the
default
installations doesn't make much sense ( like 11 P.M. for the day before
rotation). Since, VictoriaMetrics maintenances daily-indexes and it have
to repopulate it twice.

But it could be useful in conjunction with `-retentionTimezoneOffset`,
which could delay index rotation for the current day and give more time
for the prefill process.

As an example, `-retentionTimezoneOffset=4h` adds an additional 4 hours
to the rotation time and `-storage.idbPrefillStart` could be changed
accordingly.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9393

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).

---------

Signed-off-by: f41gh7 <nik@victoriametrics.com>
Co-authored-by: Roman Khavronenko <roman@victoriametrics.com>
2025-07-30 19:15:05 +03:00
Zakhar Bessarab
62ab06d635 docs/changelog: follow-up for 11cfdb8d
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-07-29 13:52:43 +04:00
Zakhar Bessarab
396cc14473 app/vmctl: allow overriding tmp files location for prometheus migration (#9513)
Previously, vmctl tried to create a tmp directory in a directory with
Prometheus snapshot. This is not always possible as snapshot can be
mounted in read-only mode.

Use a system default temporary location and allow user to customize the
tmp path in order to avoid issues with custom tmp locations.

Closes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9505

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-07-29 13:45:57 +04:00
Roman Khavronenko
f385e36b96 docs: move stream aggregation config to a sub-section (#9500)
https://docs.victoriametrics.com/victoriametrics/stream-aggregation/#configuration
section is the biggest section in the stream aggregation docs. Moving it
to a subsection should make the page easier to read.

In the future, new sub-sections are planned: `quick start` and
`examples`.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-07-28 19:10:40 +03:00
f41gh7
11cfdb8d20 docs/changelog: mention change 69760f1d0c
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-07-28 16:27:39 +02:00
Alexander Frolov
69760f1d0c discovery/kubernetes: avoid unnecessary blocking during cleanup
The `groupWatchersCleaner` iterates through all watchers, attempting to
lock them sequentially while holding the global `groupWatchersLock`.
Therefore, a large number of group watchers can cause the
`groupWatchersLock.Lock()` to block for a noticeable period.

Proposing to use `TryLock` as an optimistic case because if the watcher
lock is held, it's more likely that the watcher is still in-use so no
further cleanup is required.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9354#issuecomment-3089108889
2025-07-28 15:41:40 +02:00
Leonardo Taccari
69e8a0e247 docs/changelog: properly spell NetBSD
One byte typo fix for properly spelling NetBSD.

NetBSD is spelled with the uppercase N.
2025-07-28 15:35:34 +02:00
Roman Khavronenko
2d5b196e05 docs: mention that single-node supports HA in cluster recommendation
See context here
https://www.reddit.com/r/VictoriaMetrics/comments/1mb60ck/ha_setup_on_onprem_cluster/
Apparently, user was confused with inability of VM single-node to run in
HA.
2025-07-28 15:24:08 +02:00
Aliaksandr Valialkin
045c537a16 vendor: update github.com/VictoriaMetrics/VictoriaLogs to v0.0.0-20250727175446-3ac9ad9e7935 2025-07-28 14:46:14 +02:00
Andrii Chubatiuk
dee6bb0066 vmui: removed codeql, added reporter for eslint (#9468)
### Describe Your Changes

removed CodeQL and added ESLint annotations

<img width="1102" height="286" alt="image"
src="https://github.com/user-attachments/assets/0dc8f7de-b062-4b46-9490-82d2908da045"
/>

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-28 15:43:16 +03:00
Max Kotliar
82920393da app/vmselect/netstorage: do not retry "cannot obtain connection from the pool" errors (#9484)
Currently, all errors that occur during the handshake and dial phases
(except for timeouts) are retried in
[execOnConnWithPossibleRetry](0c4062b727/app/vmselect/netstorage/netstorage.go (L2431)).
However, such errors typically result from network issues or CPU
exhaustion on the storage side. In both cases, retrying is unlikely to
succeed and may instead contribute to additional, unnecessary load on
the system.

This PR disables retries for all errors encountered during the handshake
and dial process. The goal is to avoid redundant retry attempts in
scenarios where they are unlikely to help and may worsen the underlying
problem.

Related to
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9345

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-28 15:31:25 +03:00
Max Kotliar
7c44036aa2 docs: do not mention boringcrypto in fips docs (#9507)
### Describe Your Changes

BoryingCrypto was deprecated and is not used since go1.24, see
https://go.dev/blog/fips140

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-28 15:26:44 +03:00
Aliaksandr Valialkin
65251c8fe2 lib/{mergeset,storage}: open files inside parts in parallel
This should reduce the time needed for opening the parts on high-latency storage systems such as NFS or Ceph.

Updates https://github.com/VictoriaMetrics/VictoriaLogs/issues/517
2025-07-28 13:41:02 +02:00
Aliaksandr Valialkin
bbda00fec5 vendor: update github.com/VictoriaMetrics/VictoriaLogs to v0.0.0-20250727175446-3ac9ad9e7935 2025-07-27 20:02:31 +02:00
Aliaksandr Valialkin
8e155da0ac lib/{mergeset,storage}: close in parallel part files opened for reading
This should reduce the time needed for closing the part on high-latency
storage systems such as NFS or Ceph.

Updates https://github.com/VictoriaMetrics/VictoriaLogs/issues/517
2025-07-27 19:23:55 +02:00
Aliaksandr Valialkin
cc58d659c3 lib/{fs,filestream}: move lib/filestream.MustCloseWritersParallel() to lib/fs.MustCloseParallel()
The lib/fs.MustCloseParallel() accepts a slice of MustWriter items, which must implement only
a single method - MustWrite(). The previous lib/filestream.MustCloseWritersParallel() was
accepting CloseWriter items, which must implement Write() and Path() methods additionally
to MustClose() method. This was adding artificial restrictions on the applicability
of the MustCloseWritersParallel() method. Remove these restrictions.
2025-07-27 19:12:34 +02:00
Aliaksandr Valialkin
a05e4cf67b lib/{mergeset,storage}: store files inside in-memory parts to the persistent storage in parallel
This should reduce the time needed for converting in-memory parts to file-based parts on high-latency
storage systems such as NFS or Ceph.

Updates https://github.com/VictoriaMetrics/VictoriaLogs/issues/517
2025-07-27 18:19:22 +02:00
Aliaksandr Valialkin
3c7c3a5b0d lib/{mergeset,storage}: flush and close files inside the newly created parts in parallel
This should reduce the time needed for closing the newly created parts on high-latency
storage systems such as NFS or Ceph.

This should help https://github.com/VictoriaMetrics/VictoriaLogs/issues/517
2025-07-27 17:51:56 +02:00
Aliaksandr Valialkin
068eecf1c6 lib/fs: remove directory entries in parallel at MustRemoveDir()
This should reduce the time needed for the deletion of VictoriaLogs parts
with big number of files, which are created when wide events are ingested into VictoriaLogs
(e.g. logs with big number of log fields).

This may help improving scalability of VictoriaLogs at systems with big number of CPU cores,
which store data into high-latency storage such as Ceph or NFS.
See https://github.com/VictoriaMetrics/VictoriaLogs/issues/517
2025-07-27 17:25:17 +02:00
Aliaksandr Valialkin
4806fe02d8 lib/fs: add common path into MustSyncPath() for disabled fsync - just check that the given path exists
This removes the need of fsutil.IsFsyncDisabled() checks inside arch-specific implementations
of the mustSyncPath() function.
2025-07-27 17:14:46 +02:00
Aliaksandr Valialkin
73015bccb9 apptest: do not use "at" and "pb" import aliases for apptest and prombpmarshal packages
The import aliases may complicate maintenance of the code in the long term
if they aren't used consistently, e.g. if one file imports the apptest under the default name
while the other file imports the apptest under the "at" name.

The aliases also complicate grepping the code by apptest.* or prompbmarshal.* .
2025-07-26 01:04:50 +02:00
Aliaksandr Valialkin
da5c065f29 go.mod: update github.com/VictoriaMetrics/VictoriaLogs to v0.0.0-20250725215216-8de283002ba8 2025-07-26 00:04:13 +02:00
Aliaksandr Valialkin
eb2235d354 app/vmalert: consistently use lib/fs.MustRemoveDir() instead of os.RemoveAll() 2025-07-25 20:29:44 +02:00
Aliaksandr Valialkin
90a84f2526 apptest: consistently use lib/fs.MustRemoveDir() instead of os.RemoveAll()
This reduces the amounts of bolierplate code needed for error handling
2025-07-25 20:28:53 +02:00
Aliaksandr Valialkin
a092901e26 Makefile: add make apptest command - alias for the make integration-test
The `make apptest` is more natural because integration tests are located in the apptest directory.
2025-07-25 20:27:34 +02:00
Aliaksandr Valialkin
83da33d8cf lib/fs: simplify the code for directory removal and make it compatible with object storage (S3) and NFS
- Drop the code needed for asynchronous removal of the directory on NFS shares.
  This code was needed when VictoriaMetrics could keep open files after their deletion
  or renaming. This is no longer the case after the commit 43b24164ef .
  Now files are deleted only after all the readers close them.
  This updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/61

- Unify MustRemoveAll() and MustRemoveDirAtomic() into MustRemoveDir() and MustRemovePath()
  functions:

  - The MustRemoveDir() deletes the given directory with all its contents, in an "atomic" way:
    it creates a special `.delete-this-dir` file in the directory, then removes all its contents
    except of this file, and later removes the `.delete-this-dir` file together with the directory
    itself. This makes possible easily determining whether the given directory needs to be deleted
    after unclean shutdown - if it contains the `.delete-this-dir` file or if it is empty, it must be deleted.
    Add IsPartiallyRemovedDir() function, which can be used for detecting whether the given directory must be removed
    at starup.

    Previously the MustRemoveDirAtomic() was using a "trick" for atomic directory removal: it was "atomically" renaming
    the directory to a temporary directory with '.must-remove.' marker in the directory name, and after that it
    was removing the renamed directory. On startup all the directories with the `.must-remove.` marker were deleted
    if they are left after unclean shutdown. This "trick" doesn't work for NFS and object storage such as S3,
    since these storage systems do not support atomic renaming of directories with multiple entries inside.
    The new MustRemoveDir() function doesn't use this "trick", so it can be safely used in NFS and S3-like storage systems.

    This is based on the pull request from @func25 - https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9486/files .

  - The MustRemovePath() deletes the given file or an empty directory.

- Delete the existing parts and partitions at startup if they were partially deleted.

- Consistently use fs.MustRemoveDir() and fs.MustRemovePath() instead of os.RemoveAll() across the codebase.
  This reduces the amounts of bolierplate code related to error handling.

- Consistently use fs.MustWriteSync() instead of os.WriteFile() across the codebase.
2025-07-25 19:54:03 +02:00
Aliaksandr Valialkin
e8c622766b lib/storage/metricnamestats: consistently use lib/fs helpers instead of re-implementing them again
- Consistently use fs.IsPathExist() for checking whether the given path exists on the filesystem.

- Consistently use fs.MustWriteAtomic() for atomic store of the serialized state into file.

- Consistently panic with 'BUG:' prefix on unexpected errors.

- Read and write the state file contents in one go. This simplifies the code for loading and storing the state.
  This shouldn't increase memory usage too much, since the parsed state is already stored in RAM.

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9074
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9102
2025-07-25 15:46:31 +02:00
Fred Navruzov
7c99b710aa docs/vmanomaly: release v1.25.1 (#9496)
### Describe Your Changes

Documentation updates for vmanomaly release v1.25.1

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-24 21:28:03 +02:00
Dmytro Kozlov
690f7b1827 Makefile: add TSBS build targets (#9353)
Added a simple realisation of TSBS benchmark
2025-07-24 13:47:09 +02:00
Artem Fetishev
ad053682ab lib/storage: Minor renamings requested in #8134 (#9483)
The following renamings were requested in #8134 to be done in a separate
PR:

- Rename putTSIDToCache(s) to storeTSIDToCache(s). This is because
get/put prefixes are normally reserved for pools and ref counters. This
unclear though whether name `getTSIDFromCache` is okay in this context.
- Rename `addPartitionNolock` to `addPartitionLocked`, because the
`Locked` suffix is used everywhere else
- Rename deleteMetricIDs to saveDeletedMetricIDs, because no deletion is
actually happening. The deleted metric ids are still present in the
index. One needs to filter the deleted metric ids out after the
retrieval.

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-23 12:15:39 +02:00
Max Kotliar
dda649dd2c docs: fix "reduce CPU usage" feature entry missattributed in the changelog. 2025-07-22 17:42:50 +03:00
f41gh7
d083ff790a docs/changelog: mention netBSD builds
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-07-21 18:41:53 +02:00
Leonardo Taccari
55b9b8dfee Support NetBSD builds
Previously, it was not possible to compile netBSD binary due to missing OS constrains at lib/fs and lib/filestream packages.

 This commit fixes it by:

* apply proper constrains at lib/filestream
* Introduce statfs_t and statfs() to abstract unix internals: NetBSD
 needs to use unix.Statvfs_t and unix.Statvfs() unlike other Unix-es.
* apply proper constrain for vmctl terminal package

Related PR https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9473
2025-07-21 18:37:40 +02:00
hagen1778
783803ee32 docs: fix typos
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-07-21 18:29:58 +02:00
Artem Fetishev
05a8657c65 docs: bump lastest LTS versions
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-21 10:32:12 +00:00
Artem Fetishev
6d8ae28442 docs: Bump VictoriaMetrics version to v1.122.0
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-21 10:23:22 +00:00
Aliaksandr Valialkin
dd9a113890 docs/victoriametrics/Articles.md: move the article from TiDB upper in the list of articles, since it has higher priority 2025-07-21 12:17:54 +02:00
Aliaksandr Valialkin
46535bcf4c docs/victoriametrics/Articles.md: move articles about VictoriaLogs to https://docs.victoriametrics.com/victorialogs/articles/
See cf309d7feb
2025-07-21 12:13:46 +02:00
Artem Fetishev
2fb38b0333 Bump image version to v1.122.0 in docker compose configs
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-21 10:07:57 +00:00
Roman Khavronenko
5bcb67e508 dashboards: remove victorialogs related dashboards (#9471)
The new home for vlogs dashboards is
https://github.com/VictoriaMetrics/VictoriaLogs/tree/master/dashboards

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-07-19 14:59:19 +02:00
hagen1778
282d6fa998 docs: move vlogs articles to a sub-section
while there, add a bunch of vlogs articles we've missed to add.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-07-19 14:58:20 +02:00
Mathias Palmersheim
2027233b33 added alert statistics dashboard (#9427)
### Describe Your Changes

adds alert statistics dashboard #8593

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-07-18 12:50:24 -05:00
Aliaksandr Valialkin
21c8ae4d02 docs/victoriametrics/Articles.md: add a link to https://www.truefoundry.com/blog/victorialogs-vs-loki 2025-07-18 17:46:41 +02:00
Artem Fetishev
f5fcfd8e46 docs/CHANGELOG.md: cut v1.122.0
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-18 13:59:10 +00:00
Aliaksandr Valialkin
9d9bea0348 lib/{storage,mergeset}: make sure the newly created data part is visible in the parent directory before storing it in parts.json
The newly created data part could become missing after unclean shutdown (such as hardware power off),
since the contents of the parent directory wasn't synced to disk before storing the newly created data part in the parts.json file.

Fix this by syncing the parent directory contents before storing the newly created part in the parts.json file.

This commit is based on https://github.com/VictoriaMetrics/VictoriaLogs/pull/507
2025-07-18 14:56:06 +02:00
Artem Fetishev
cfcb74381e deployment: update base Docker image from alpine:3.22.0 to alpine:3.22.1
See https://www.alpinelinux.org/posts/Alpine-3.19.8-3.20.7-3.21.4-3.22.1-released.html

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-18 12:19:55 +00:00
hagen1778
84f95f362a docs: add Scaling Observability: Why TiDB Moved from Prometheus to VictoriaMetrics
https://www.pingcap.com/blog/tidb-observability-migrating-prometheus-victoriametrics/
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-07-18 11:27:27 +02:00
Nikolay
eb1164278e lib/mergeset: reduce memory allocations on blockcache misses
This commit adds tmp inmemory and data blocks buffers for
index search requests. It allows to reduce memory allocations on block
cache misses. Since block cache puts block into cache only on after
configured number of cache misses.

Related PR https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9324
2025-07-18 10:47:30 +02:00
Max Kotliar
01088cc513 lib/netutil: reuse idle connections more actively (#9464)
Related to
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9345. While it
doesn't directly fix the issue, it should help improve the situation. We
should do fewer dials and handshakes, hence fewer chances to make an
error.

- Keep idle connection for a longer time, 30s -> 120s.
- Keep at least two established connections at all times.

Some stats from our internal deployments (note that the screenshot
reflects a minimum of four connections, whereas the final version uses
only two):

1:
<img width="1508" height="623" alt="Screenshot 2025-07-17 at 16 46 42"
src="https://github.com/user-attachments/assets/ce5c4007-8d4d-40d0-b8bc-c890e8f97208"
/>
<img width="1510" height="625" alt="Screenshot 2025-07-17 at 16 46 54"
src="https://github.com/user-attachments/assets/ed7592b8-4123-4c57-8131-0c392216477f"
/>

2:
<img width="1497" height="488" alt="Screenshot 2025-07-17 at 16 47 16"
src="https://github.com/user-attachments/assets/c1ff33ca-1cc0-4d71-ae37-c6ff192b9525"
/>
<img width="1496" height="489" alt="Screenshot 2025-07-17 at 16 47 25"
src="https://github.com/user-attachments/assets/688f136c-67a4-44a4-9855-b9a6a369cd49"
/>

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-18 10:52:09 +03:00
Andrei Baidarov
4d0cdf1dc6 lib/storage: non-empty extDB in search tests/benchmarks (#9446)
Current tests do not cover search from extDB
2025-07-18 09:00:45 +02:00
Max Kotliar
11bb47a03b dashboards: TCP connections shows spikes on small time ranges (#9465)
### Describe Your Changes

When `$__interval` is small and close to the scrape interval, we start
losing some data points, which can cause the sum to show misleading
spikes. This change ensures that the minimum interval does not go below
1m to avoid such issues.

The query works fine for long time ranges, like 7d, 30d, where interval
is bigger than 1m

The query:
```
sum(max_over_time(vm_tcplistener_conns{job=~"$job", instance=~"$instance"}[$__interval])) by(job)
```

Before:
<img width="1511" height="665" alt="Screenshot 2025-07-17 at 17 22 23"
src="https://github.com/user-attachments/assets/b15dd3db-cb5e-4c9d-9ce4-4a665c38273e"
/>

After:
<img width="1510" height="665" alt="Screenshot 2025-07-17 at 17 22 44"
src="https://github.com/user-attachments/assets/3f82f6d2-53e4-4a20-830e-2073255f6c01"
/>

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-18 08:23:05 +03:00
f41gh7
2f8ad3aaf4 docs: update changelog description
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-07-17 20:55:42 +02:00
Alexander Frolov
617e19a6d7 lib/cgroup: properly set process_cpu_cores_available metric
This commit respects online CPU count for process_cpu_cores_available metric. Since CPUQuota may exceed it.


 Detailed description:

 There might be a case when `getCPUQuota()` returns a value bigger than
available logic CPU cores. In this case the lower value should be used.

These changes also reflect upcoming go1.25 changes
https://tip.golang.org/doc/go1.25#container-aware-gomaxprocs
> If the CPU bandwidth limit is lower than the number of logical CPUs
available, GOMAXPROCS will default to the lower limit

In practice that happens with [CPU
Manager](https://kubernetes.io/blog/2022/12/27/cpumanager-ga/) enabled.
It requires setting `/sys/devices/system/cpu/online` which shows the
total number of cores on a node. The container doesn't have any cgroup
limits, but it's pinned to a limited subset of cores.
```
root@vmselect:/# cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us
-1
root@vmselect:/# cat /sys/fs/cgroup/cpu/cpu.cfs_period_us
100000
root@vmselect:/# cat /sys/devices/system/cpu/online
0-255
```

go1.25 and go.uber.org/automaxprocs don't look into
`/sys/devices/system/cpu/online`, VictoriaMetrics does
2025-07-17 20:46:49 +02:00
Alexander Frolov
8d11b9f4a6 lib/promscrape: chunkedbuffer double-free
The chunkedbuffer is released twice, leading to concurrent use of the
buffer after it's acquired from a pool by two different goroutines.


 Issue was introduced at v1.115.0 at the following commit 5b87aff830
2025-07-17 20:37:39 +02:00
Andrei Baidarov
0a2213dbd6 apptest: support more API (#9462)
Extracted from #8134
2025-07-17 18:43:26 +02:00
Fred Navruzov
509cbe7b05 docs/vmanomaly: release v1.25.0 (#9455)
### Describe Your Changes

Doc updates to release v1.25.0, including
- config hot reload
- environment variable config placeholders
- cross-linking VM Operator support
- and other connected docs changes

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-17 16:11:25 +02:00
Max Kotliar
bf0dc413bf Use empty string when EXTRA_DOCKER_TAG_SUFFIX not provided. (#9458)
### Describe Your Changes

Previously, if I run `make publish-vmstorage` it composed the tag name
like:

```
docker.io/victoriametrics/vmstorage:heads-tcpdialer-increase-idle-timeout-0-g1b20c2dbd3-dirty-84b03c0eEXTRA_DOCKER_TAG_SUFFIX
```

It would work okay if I explisitly provide empty
`EXTRA_DOCKER_TAG_SUFFIX=` env var.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-17 17:03:21 +03:00
Nikolay
5794cf46d7 app/vmstorage: enable metric name stats tracker by default (#9457)
This feature helps to understand cardinality contribution by metric
names and it doesn't require extra resources. It's advisable to enable
it by default.

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).

---------

Signed-off-by: f41gh7 <nik@victoriametrics.com>
Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-07-17 12:30:00 +02:00
Phuong Le
6da0390946 lib/storage: add test case for deduplication to keep first and last samples (#9376)
Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-07-17 12:21:00 +02:00
Roman Khavronenko
704b65499e docs/vmalert: mention a common mistake of using dynamic label values (#9441)
The new tip added based on recent support case.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-07-17 12:20:42 +02:00
Artur Minchukou
582606716d app/vmui: add CI workflow for vmui with lint, typecheck, and testing (#9435)
### Describe Your Changes

Added CI workflow for vmui with lint, typecheck, and testing.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).

---------

Co-authored-by: Andrii Chubatiuk <achubatiuk@victoriametrics.com>
2025-07-17 12:19:54 +02:00
Roman Khavronenko
194df32a30 Revert "app/vmselect: respect staleness markers when calculating rate and increase functions" (#9451)
This reverts commit 63e1bf5d97. The reason
for revert is that the change makes increase/rate behavior less
predictable for users. See
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9420.

Another negative impact of this change is that it negatively affects
recording rules that calculate increases or rates over time series on
big intervals. For example,
`increase(http_errors_total{instance="foo"}[30d])` would stop producing
results if `http_errors_total{instance="foo"}` was marked as stale. But
this is logically incorrect, as `http_errors_total{instance="foo"}` over
last 30d should still return results.

-------------

This change doesn't revert
63e1bf5d97
completely. It keeps changes made to `removeCounterResets` in order to
preserve original `staleNaN` values. Before, `staleNaN` were compared
with float values and producing `NaN` instead. Which could confuse us in
future. So keeping the fix and tests. It shouldn't have any negative
effect.

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-07-17 12:15:10 +02:00
nemobis
cb83ab7379 docs: Fix typo in changelog (#9456)
### Describe Your Changes
Typo fix.
### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-17 12:14:52 +02:00
Andrii Chubatiuk
c6e107c2e8 app/vmselect invalid notifiers and metadata paths (#9421)
fix vmselect /api/v1/notifiers and metadata paths in a cluster branch,
due to these inconsistencies both endpoints are not available

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).

---------

Co-authored-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
Co-authored-by: Max Kotliar <mkotlyar@victoriametrics.com>
2025-07-16 16:38:26 +04:00
Andrii Chubatiuk
a46d2727cf lib/license: do not use -eula flag for license verification (#914)
* made -acceptEULA flag no-op

* Update lib/license/copyrights.go

Co-authored-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>

* Update lib/license/copyrights.go

* docs/changelog: add an update note for the change

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>

* docs/changelog: update formatting

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
Co-authored-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-07-16 16:28:46 +04:00
Zakhar Bessarab
b167f3f270 docs/changelog: fix order of items after 8d511e8d
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-07-16 16:15:50 +04:00
Zakhar Bessarab
8d511e8d09 app/vmstorage: delete old snapshots after 3 days by default (#9438)
Previously, snapshots were never deleted automatically. This lead to
disk space waste in case snapshots were left behind and never deleted,
which happened in case of backups failure. This required manual
investigation and snapshots cleanup.

This change enables removal of snapshots older than 3 days by default.
This should give enough time to upload backup in time and also make sure
old snapshots are not wasting disk space.

Closes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9344

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-07-16 16:09:58 +04:00
Artem Fetishev
834457f0c6 Makefile: remove vlogs build targets (#9434)
### Describe Your Changes

VictoriaLogs has been moved to a separate repository. Remove remaining
vlogs build rules from VictoriaMetrics.
 
### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [x] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-15 15:50:33 +03:00
Max Kotliar
0308880418 lib/filesyste: make golangci-lint pass on macos (fields are used under build tag) 2025-07-15 14:50:32 +03:00
Andrii Chubatiuk
db39f045e1 ci: golangci-lint 1.6.x -> 2.2.1 2025-07-15 14:27:15 +03:00
Andrii Chubatiuk
336e4abc5c ci: do not run go actions on UI changes (#9440)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-15 14:08:46 +03:00
Max Kotliar
7d75e0353b app/vmagent/remotewrite: Prevent panic during block re-pack on protocol downgrade. (#9419)
### Describe Your Changes

Also, the protocol is downgraded only if vmagent can re-pack the block
successfully. It would prevent an accidental downgrade on a corrupted
block.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9417

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-15 13:43:30 +03:00
Andrii Chubatiuk
4576b67c0f ci: free disk space before main workflow (#9432)
Removing unneeded packages before running build to prevent build failures like this one - https://github.com/VictoriaMetrics/VictoriaMetrics-enterprise/actions/runs/16220839709/job/45803120572
2025-07-15 08:42:37 +04:00
Aliaksandr Valialkin
e41714f213 go.mod: do not use "replace" directive for overriding the version of the github.com/VictoriaMetrics/VictoriaLogs package
Refer to the needed package directly in the "require" directive.
This should make more useful the prefixes for file locations in the output logs
generated by VictoriaMetrics components.

See https://github.com/VictoriaMetrics/VictoriaLogs/issues/431#issuecomment-3071313506 for details.
2025-07-15 01:17:48 +02:00
Aliaksandr Valialkin
15242a70a7 vendor: run make vendor-update 2025-07-15 00:26:39 +02:00
Aliaksandr Valialkin
86cf5b47e1 lib/querytracer: compare time.Time vars with time.Time.Equal() instead of plain comparison with ==
See https://pkg.go.dev/time#Time on why the "t1 == t2" comparison may result to issues.
2025-07-15 00:20:51 +02:00
Aliaksandr Valialkin
4aa179e4f5 lib/netutil: do not use unnamed field of type connMetrics inside TCPListener struct, since it is too confusing
Give it a name - cm, and refer to its' fields explicitly.
2025-07-15 00:15:57 +02:00
Aliaksandr Valialkin
4f915b0278 all: consistently start error fmt.Errorf() messages with small letter 2025-07-15 00:12:40 +02:00
Aliaksandr Valialkin
dc14513009 all: replace strings.Replace(..., -1) with strings.ReplaceAll(...) 2025-07-14 23:58:39 +02:00
Aliaksandr Valialkin
02e15f1cc5 app/vmselect/vmui: run make vmui-update after the commit 7dc79a5d85
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9428
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9388
2025-07-14 21:38:53 +02:00
Aliaksandr Valialkin
1a8e9b3b15 app/vmui/Makefile: remove make vmui-logs-update command, since it became obsolete after 7dc79a5d85
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9428
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9388
2025-07-14 21:33:48 +02:00
Artur Minchukou
7dc79a5d85 app/vmui: remove all the code related to VictoriaLogs (#9428)
### Describe Your Changes

Related issue: #9388

- removed all the code related to VictoriaLogs
- updated dependencies to the latest versions
- removed unnecessary `React` import from components
- removed deprecated dependencies such as `lodash.get`,
`@babel/plugin-proposal-nullish-coalescing-operator`,
`@babel/plugin-proposal-private-property-in-object`
- removed unused packages
- fixed proxy for local playground development (after refresh the page
app cannot properly parse the `/#/` in the path)

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-14 21:29:14 +02:00
Roman Khavronenko
40ab285fb9 docs: update troubleshooting docs for vmalert (#9373)
Based on https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9343

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-07-14 20:48:50 +02:00
Max Kotliar
5b0c861915 docs/changelog: Clarify component (vmagent) in update note. 2025-07-14 15:39:50 +03:00
Andrei Baidarov
1ae28356cc lib/storage: add TestMustOpenIndexDBTables_* (#9418)
Add unit tests that verify filesystem hierarchy of the indexdb after
opening the storage and after rotation. The test have been originally
added in #8134 but are still applicable to the current version and will
also reduce the diff.

Co-authored-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-10 15:42:11 +02:00
f41gh7
22f34284be deployment: update Go builder from Go1.24.4 to Go1.24.5
See https://github.com/golang/go/issues?q=milestone%3AGo1.24.5+label%3ACherryPickApproved
2025-07-10 13:56:21 +02:00
Andrei Baidarov
a00d5cf4b5 lib/storage: move methods from Storage to indexDB (#9416)
- Move `prefetchMetricNames`, `SearchMetricNames`, and
`SearchLabelValues` from `Storage` to `indexDB`
- Rename `searchLabelValuesWithFiltersOnTimeRange` to
`searchLabelValuesOnTimeRange`
- Rename `searchLabelValuesWithFiltersOnDate` to
`searchLabelValuesOnDate`

Extracted from #8134.

Co-authored-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-10 13:16:29 +02:00
Max Kotliar
dde08ad92c docs/changelog: Enhance the release guide (#9405)
### Describe Your Changes

- Split the release process into two steps.
- Add some links 
- Described in more details what should be done to check branches in
sync.
- Added some small checks, like running tests, and testing final release
on sandbox.
- Changed the order of some actions (like build final image before
publish release).]

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development
goals](https://docs.victoriametrics.com/victoriametrics/goals/).
2025-07-10 12:14:17 +03:00
Andrei Baidarov
01a2d43c4c lib/storage: refactor TestStorageRotateIndexDB_* tests (#9414)
Extracted from #8134
2025-07-09 15:29:03 +02:00
Andrei Baidarov
3a5356ee6f lib/storage: add DebugFlush methods for partition/table (#9413)
Extracted from #8134
2025-07-09 15:20:35 +02:00
Andrei Baidarov
678786ef7e lib/storage: make create(Global|PerDay)Indexes idb methods (#9412)
Extracted from #8134
2025-07-09 15:03:58 +02:00
Andrei Baidarov
25a1428329 lib/storage: pass timestamp explicitly in tests (#9411)
Extracted from #8134
2025-07-09 14:44:40 +02:00
Andrei Baidarov
28c0f41d1a lib/storage: move SearchGraphitePaths to indexDB (#9410)
`SearchGraphitePaths` does not depend on storage, so move it with dependencies to `index_db.go`.
Extracted from #8134.
2025-07-09 14:19:11 +02:00
Andrei Baidarov
0a6f6d5793 apptest: rename DeleteSeries to APIV1AdminTSDBDeleteSeries and implement it for vmsingle (#9409)
Extracted changes from #8134
2025-07-09 13:42:57 +02:00
Andrei Baidarov
b93ea6eba6 do not depend on platform, use maxInt64 explicilty (#9406)
Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8134
2025-07-08 13:26:04 +02:00
Andrei Baidarov
98efb80727 lib/storage: rewrite TestStorageDeleteSeries_TooManyTimeseries
Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8134
2025-07-08 13:24:57 +02:00
Andrei Baidarov
a1323196e1 lib/storage: refactor TestIndexDB
Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8134
2025-07-08 11:03:19 +02:00
Andrei Baidarov
d25995aeb0 lib/storage: add TestStorageDeletePendingSeries
Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8134
2025-07-08 11:01:38 +02:00
Andrei Baidarov
cc0ebec5fb lib/storage: rewrite TestStorageDeleteSeries_CachesAreUpdatedOrReset
Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8134
2025-07-08 11:00:15 +02:00
Andrei Baidarov
627c536dfc lib/storage: use explicit TimeRange{0, math.MaxInt} for all time period search
Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8134
2025-07-08 10:56:21 +02:00
Andrei Baidarov
2f4fea1d11 lib/storage: add and use testCreatePartition helper
Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8134
2025-07-08 10:55:13 +02:00
Andrei Baidarov
dfb4e3f5bb lib/storage: use real storage in TestUpdateCurrHourMetricIDs
Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8134
2025-07-08 10:54:20 +02:00
Dmytro Kozlov
b77904fabe deployment/docker: fix datasource provision file for cluster
When you try to run `make docker-cluster-up` and try to check metrics in 
the Explore page of the Grafana, you will see the basic auth request. If
you enter the correct login and password from the `auth-vm-cluster.yml`
it will continue to ask about the username and password. It happens
because the datasource is configured to ask for data vmauth, but in the
configuration, no auth information is provided.

Added the basich auth info to the datasource provision file
2025-07-08 10:53:44 +02:00
Dima Shur
7c5cae9efc docs/backups: add notes for snapshots troubleshooting, custom hostname usage (#9341)
Adding note for -dst config. Adding additional reference for snapshot troubleshooting for better accessibility

Making documentation easier to use following customer issues
2025-07-08 10:34:20 +04:00
Max Kotliar
f56d7c4045 docs: mention new LTS releases 2025-07-07 15:31:30 +03:00
Max Kotliar
ccc093e0f1 docs: update VictoriaMetrics Docker image tags to v1.121.0 2025-07-07 15:20:59 +03:00
Max Kotliar
f8fcc58396 deployment: update VictoriaMetrics Docker image tags to v1.121.0 2025-07-07 15:13:13 +03:00
Artem Fetishev
d81cebe287 apptest: Do not configure cluster storageDataPath and retentionPeriod by default (#9391)
Defaults are set only in StartDefaultCluster()

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-07 13:37:59 +02:00
Artem Fetishev
cdfdf791a4 apptest: Fix TestClusterMultiTenantSelect in master
TestClusterMultiTenantSelect passes in cluster branch but fails in master.
Integration tests must pass in any branch since they do not distinguish
between master and cluster.

The test fails because the multitenant_test.go is different in master and
cluster. This commit makes the file identical in both branches.

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-07 11:41:33 +02:00
Andrii Chubatiuk
bee6926a89 apptest: removed victorialogs tests (#9389)
fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9387
2025-07-07 10:45:02 +02:00
Matt Cocking
c6ac25bd56 docs/victoriametrics: fix vmalert activeAt example so from is before to (#9381)
### Describe Your Changes

The example for using the `activeAt` template in `vmalert.md` was wrong,
with the `from` field being before the `to` field. This switches them
round to be correct.

### Checklist

The following checks are **mandatory**:

- [X] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-07-07 11:42:53 +08:00
Aliaksandr Valialkin
3babb0f276 deployment/docker: remove all the code related to VictoriaLogs, since it has been migrated to https://github.com/VictoriaMetrics/VictoriaLogs/ 2025-07-07 03:43:05 +02:00
Aliaksandr Valialkin
d1d98f39b5 lib/{logstorage,prefixfilter}: remove these packages, since they have been moved to https://github.com/VictoriaMetrics/VictoriaLogs/ repository 2025-07-07 03:25:25 +02:00
Aliaksandr Valialkin
54cc6fc1df app/vlogsgenerator: remove the code here, since it has been moved to https://github.com/VictoriaMetrics/VictoriaLogs/ 2025-07-07 03:15:33 +02:00
Aliaksandr Valialkin
0b5f53fe7b app: remove VictoriaLogs-related apps, since they are moved to a separate repository - https://github.com/VictoriaMetrics/VictoriaLogs/ 2025-07-07 02:58:54 +02:00
Aliaksandr Valialkin
624497a954 docs/victorialogs: remove VictoriaLogs, since now they are located in the https://github.com/VictoriaMetrics/VictoriaLogs/ repository
Docs at https://github.com/VictoriaMetrics/VictoriaLogs/ are automatically synced to https://docs.victoriametrics.com/victorialogs/
2025-07-07 02:53:04 +02:00
Aliaksandr Valialkin
6d3d731851 docs/victoriametrics/query-stats.md: manually fix the improper available_from construction added in the commit 6751e43975
The `available_from` construction must have the form {{% available_from "#" %}}
instead of {{% available_from "tip" %}} in order to be able to automatically update before the release
with the `make docs-update-version` command.
See https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist
and https://docs.victoriametrics.com/victoriametrics/release-guide/#release-version-and-docker-images
2025-07-06 20:34:00 +02:00
Aliaksandr Valialkin
dc38e17f79 docs/victoriametrics/CONTRIBUTING.md: mention that the pull request must conform development goals from https://docs.victoriametrics.com/victoriametrics/goals/ 2025-07-06 20:10:09 +02:00
Aliaksandr Valialkin
9146c90ae1 .github/pull_request_template.md: add a link to https://docs.victoriametrics.com/victoriametrics/goals/
Users who submit pull requests must be aware of https://docs.victoriametrics.com/victoriametrics/goals/
and the pull request must be aligned with this document.
2025-07-06 20:08:28 +02:00
Aliaksandr Valialkin
a93ff1a6ec docs/Makefile: move the comments for make docs-images-to-webp command into the correct place
The comments weren't moved to the correct place in the commit 36bc458e9e

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6825

P.S. it was a strange decision to use a bloated docker image from VictoriaMetrics/vmdocs repository
for the conversion of the `*.png` files to `*.webp` files instead of the specialized slim image - https://hub.docker.com/r/elswork/cwebp .
2025-07-06 19:55:55 +02:00
Aliaksandr Valialkin
8646b73efc lib/timeutil: put TryParseUnixTimestamp function here
This allows avoiding precision loss at VictoriaLogs query time when parsing fractional unix timestamps with millisecond, microsecond and nanosecond precisions.

This is a follow-up for 1d0e96c8d2

See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8767#discussion_r2051657518
2025-07-06 17:17:07 +02:00
Aliaksandr Valialkin
6452ff8624 app/vmauth: fix tests after the commit 524f58c78c
The remoteAddr and requestURI aren't sent to the client in the error response after the commit 524f58c78c .
They are logged locally instead. This increases security by not exposing potentially sensitive information (remoteAddr and requestURI) to the client.
This doesn't reduce debuggability, since remoteAddr and requestURI are logged locally together with the error message.
2025-07-06 16:36:22 +02:00
Aliaksandr Valialkin
1fa5ecd981 lib/logstorage: optimize tryParseUint64() a bit 2025-07-06 16:31:26 +02:00
Aliaksandr Valialkin
1d0e96c8d2 lib/logstorage: rewrite TryParseUnixTimestamp(), so it doesnt loose precision when parsing fractional timestamps with millisecond, microsecond and nanosecond precision
- Optimize TryParseUnixTimestamp() by using custom parsing logic instead of generic strconv.Parse* functions.
- Add benchmarks for TryParseUnixTimestamp().
- Add more tests for edge cases with various unix timestamps.

See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8767#discussion_r2051657518

This is a follow-up for 7294ffcdfc
2025-07-06 16:10:59 +02:00
Aliaksandr Valialkin
bb2945b944 docs/victorialogs/CHANGELOG.md: move the description of the format "<time:...>" improvement into the correct place
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8767
This is a follow-up for 7294ffcdfc
2025-07-06 12:38:32 +02:00
Vadim Alekseev
7294ffcdfc lib/logstorage: add support for parsing Unix timestamp in format pipe (#8767)
### Describe Your Changes

This PR adds support for parsing Unix timestamps (both integer and
float) in the format pipe using the `time:` prefix.
The timestamp precision (seconds, milliseconds, microseconds, or
nanoseconds) is automatically determined based on the value.

It might be worth creating a new prefix for this rather than reusing
`time:`, but I haven't found any compelling reason to extend the syntax.

### Checklist

The following checks are **mandatory**:

- [X] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
Co-authored-by: Aliaksandr Valialkin <valyala@gmail.com>
2025-07-06 12:33:13 +02:00
Aliaksandr Valialkin
524f58c78c lib/httpserver: log the client address additionally to the requestURI in the SendPrometheusError()
This should allow detecting the client, which led to the error logged via SendPrometheusError() function,
e.g. this improves troubleshooting of the logged errors.

This is a follow-up for c9bb4ddeed
2025-07-05 23:51:23 +02:00
f41gh7
e4fc202ab8 docs/guides: add missing receiver to opentelemetry guide
Previously configuration example missed mandatory receiver for logs pipeline

Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-07-05 12:02:16 +02:00
Max Kotliar
b1003c0e65 docs/CHANGELOG.md: cut v1.121.0 2025-07-04 13:07:59 +00:00
Max Kotliar
4c5cde71eb app/vmselect: run make vmui-update 2025-07-04 12:44:00 +00:00
Max Kotliar
62611ee384 docs/victoriametrics/changelog: fix typo 2025-07-04 11:18:35 +00:00
Max Kotliar
3d7420d135 docs/victoriametrics/changelog: Add an update note on -retryMaxTime flag deprecation 2025-07-04 10:53:42 +00:00
f41gh7
9e9d697a31 docs/changelog: adjust changelog entry ordering
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-07-04 10:35:25 +02:00
Andrii Chubatiuk
f0859403da lib/promscrape: added label_limit global and per job scrape param (#7795)
This commit introduces new scrape config option - `label_limit`. Which defines labels count limit for time series.
Whole scrape will be discarded In case of limit breach.
 This option could also be defined with label `__label_limit__` during scrape relabeling process and globally for all scrape targets.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7660 and https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3233
2025-07-04 10:18:23 +02:00
Benjamin Nichols-Farquhar
63e133fe04 app/vmalert: introduce new flag replay.ruleEvaluationConcurrency
As discussed in https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7387 we want a way to speed up execution within the replay of a single rule in vmalert.

This commit adds the flag `replay.singleRuleEvaluationConcurrency` which
limits the concurrency for requests within the replay of a single
rule.

Related to https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7387
2025-07-04 10:13:43 +02:00
leiwingqueen
e049bdcfbd app/vmagent: rename flag remoteWrite.retryMaxTime
This commit renames flag `remoteWrite.retryMaxTime` into `remoteWrite.retryMaxInterval`. New name aligns with corresponding `MinInterval` flag. Previous flag name still could be used, but vmagent will log warning message with suggested migration.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9169
2025-07-03 18:28:51 +02:00
Vadim Alekseev
53b2082f53 deployment/docker: add configuration examples of vlagent for Docker
Modified the existing HA setups to use vlagent instead of writing to two
sources

Related to https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9328
2025-07-03 18:18:54 +02:00
Max Kotliar
d6a7dc0ea0 lib/fs: enhance MustReadAt panic message
enhance `MustReadAt` panic message to include filename for easier debugging of out-of-range read

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9106
2025-07-03 18:17:54 +02:00
f41gh7
28fb87baea lib/fs: make linter happy for windows build
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-07-03 18:12:16 +02:00
Andrei Baidarov
1799478438 apptest: Add an integration test for /graphite/metrics/index.json (#9357)
While working on #8134 it has been discovered that
`/graphite/index.json` always returns an empty result. This PR adds a
test and a fix. This fix is a no-op for the master but adding it here in
order to reduce the diff in #8134.

Co-authored-by: Artem Fetishev <149964189+rtm0@users.noreply.github.com>
Co-authored-by: Artem Fetishev <rtm@victoriametrics.com>
2025-07-03 15:14:11 +02:00
Olexandr88
dd40ed2456 docs: add links to codecov, release, A+, license icons (#9335)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-07-03 11:40:35 +02:00
Hui Wang
420f6b322e vmalert: fix alerts state restoration for alerting rule using templat… (#9348)
…ing in the labels

fix https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9305

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-07-03 11:16:00 +02:00
Andrii Chubatiuk
8eb88798ca lib/streamaggr: properly clean quantiles output state on flush (#9351)
### Describe Your Changes

fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9350

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-07-03 10:28:30 +02:00
Hui Wang
6a71c53c41 vmalert: respect group order defined in the rule file during replay m… (#9349)
…ode to allow chained group if needed

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9334
2025-07-03 10:26:09 +02:00
Phuong Le
746cea61d0 VictoriaLogs: Add metrics to track the retention.maxDiskSpaceUsageBytes flag (#9319)
- `vl_max_disk_space_usage_bytes{path}` reports the configured maximum
disk space usage limit for the storage path. It helps to show the limit
on the dashboard.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9320
2025-07-03 08:29:26 +02:00
Phuong Le
ef88302975 VictoriaLogs: add message processor metrics (#9316)
Add metrics to track the behavior of the message processor:

- `vl_insert_processors_count` tracks the current number of active log
message processors.
- `vl_insert_flush_duration_seconds{type="protocol"}` measures the time
taken to flush log data from recently parsed logs to the underlying
storage system (in-memory buffering, remote storage nodes, or local
storage).

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9320

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-03 08:07:39 +02:00
Phuong Le
857dd8edec VictoriaLogs: fix rate_sum() inconsistency between normal queries and vmalert recording rules (#9304)
Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9303

Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
2025-07-03 07:25:08 +02:00
Mac G
fedb5bbc9a docs/readme: fix typo in metric name
Fix typo in metric name mentioned in doc: vm_rows_ignored_total
2025-07-02 19:37:16 +04:00
Zakhar Bessarab
96633a3c4e app/vmbackupmanager: use "lib/snapshot" for snapshot operations
Re-use existing `lib/snapshot` for snapshot operations in order to reduce code duplicates and unify supported options and error handling.

Previously, vmbackupmanager did not support `snapshot.tls*` options and did not handle errors in a same was as vmbackup does.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9340
2025-07-02 14:44:23 +02:00
Max Kotliar
1a1e4fe2d2 lib/license: improve error message when an empty license is provided (#911) 2025-07-02 14:06:36 +02:00
Yury Molodov
d455c8afa1 vmui: disable autocomplete popup on initial page load
When the page loads, the query field automatically receives focus, which
is expected. However, this also immediately opens the autocomplete
popup, triggering an unnecessary request and showing suggestions before
the user starts typing.

 This PR commit the autocomplete popup from opening on initial page
load.

Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9342
2025-07-02 13:53:55 +02:00
Nikolay
93843a1faf docs/release-guide: mention release candidate tagging process
This commits changes release process by introducing new intermediate
docker image tag with `-rcY` suffix. It's needed to properly test
releases for possible regressions without need to erase release docker
images. Which could be cached by some proxy and actually used in
production.

 Release candidate image must re-tagged into final release via make
command.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9136
2025-07-02 13:48:04 +02:00
Benjamin Nichols-Farquhar
994dadb4d5 lib/storage: Introduce vm_cache_eviction_bytes_total metric
This commit adds the following new metric `vm_cache_eviction_bytes_total` for tsid, metricName and metricIDs caches backed by workingset cache.

 The problem this is attempting to solve is doing fine grained tuning for
caches on large high churn, high query load VictoriaMetrics deployments.

Cache performance in those scenarios is critical for cluster
performance, however for stability reasons its imperative not to provide
_too much_ cache space compared to available memory or there becomes a
risk of OOM which can easily destabilize a cluster.

Given the cost of memory, especially for large deployments, there is
therefore a need to optimize cache usage to be near the minimum required
to provide acceptable performance under churn, ingestion and query
loads.

VM provides an excellent set of flags for configuring this cache
performance(size and expiry and removal percentage).

However specifically when tuning `prevCacheRemovalPercent` and
`cacheExpireDuration` it can be hard to known exactly what impact
they're having. Sometimes its very clear when theres cyclical behavior
that cacheExpireDuration is involved, but in other scenarios it can be
very unclear why cache miss rate goes up.

Specifically when attempting to debug spikes in cache miss rate there
are questions that are hard to answer:

* Did a new workload come in that was poorly cached?
* Were caches rotated due to expiry and the `prev` cache contained many
active entries due to limited cache size?
* Where the caches rotated due to miss percentage and our tuning is too
aggressive?

In many of these debugging scenarios it would be greatly helpful to have
explicit metrics on how many bytes of key caches were evicted and for
what reasons, it then becomes trivial to associate spikes in eviction
for a specific reason with a miss rate spike that causes poor
performance. The appropriate tuning them becomes much more obvious.

Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9293
2025-07-02 13:41:54 +02:00
hagen1778
469b337707 docs: refresh FAQ.md
Partially based on https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9244

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-07-01 14:20:42 +02:00
dependabot[bot]
2b131c13b5 build(deps): bump github.com/go-viper/mapstructure/v2 from 2.2.1 to 2.3.0 (#9299)
Bumps
[github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure)
from 2.2.1 to 2.3.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/go-viper/mapstructure/releases">github.com/go-viper/mapstructure/v2's
releases</a>.</em></p>
<blockquote>
<h2>v2.3.0</h2>
<h2>What's Changed</h2>
<ul>
<li>build(deps): bump actions/checkout from 4.1.7 to 4.2.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/46">go-viper/mapstructure#46</a></li>
<li>build(deps): bump golangci/golangci-lint-action from 6.1.0 to 6.1.1
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/47">go-viper/mapstructure#47</a></li>
<li>[enhancement] Add check for <code>reflect.Value</code> in
<code>ComposeDecodeHookFunc</code> by <a
href="https://github.com/mahadzaryab1"><code>@​mahadzaryab1</code></a>
in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/52">go-viper/mapstructure#52</a></li>
<li>build(deps): bump actions/setup-go from 5.0.2 to 5.1.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/51">go-viper/mapstructure#51</a></li>
<li>build(deps): bump actions/checkout from 4.2.0 to 4.2.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/50">go-viper/mapstructure#50</a></li>
<li>build(deps): bump actions/setup-go from 5.1.0 to 5.2.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/55">go-viper/mapstructure#55</a></li>
<li>build(deps): bump actions/setup-go from 5.2.0 to 5.3.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/58">go-viper/mapstructure#58</a></li>
<li>ci: add Go 1.24 to the test matrix by <a
href="https://github.com/sagikazarmark"><code>@​sagikazarmark</code></a>
in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/74">go-viper/mapstructure#74</a></li>
<li>build(deps): bump golangci/golangci-lint-action from 6.1.1 to 6.5.0
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/72">go-viper/mapstructure#72</a></li>
<li>build(deps): bump golangci/golangci-lint-action from 6.5.0 to 6.5.1
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/76">go-viper/mapstructure#76</a></li>
<li>build(deps): bump actions/setup-go from 5.3.0 to 5.4.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/78">go-viper/mapstructure#78</a></li>
<li>feat: add decode hook for netip.Prefix by <a
href="https://github.com/tklauser"><code>@​tklauser</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/85">go-viper/mapstructure#85</a></li>
<li>Updates by <a
href="https://github.com/sagikazarmark"><code>@​sagikazarmark</code></a>
in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/86">go-viper/mapstructure#86</a></li>
<li>build(deps): bump github/codeql-action from 2.13.4 to 3.28.15 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/87">go-viper/mapstructure#87</a></li>
<li>build(deps): bump actions/setup-go from 5.4.0 to 5.5.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/93">go-viper/mapstructure#93</a></li>
<li>build(deps): bump github/codeql-action from 3.28.15 to 3.28.17 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/92">go-viper/mapstructure#92</a></li>
<li>build(deps): bump github/codeql-action from 3.28.17 to 3.28.19 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/97">go-viper/mapstructure#97</a></li>
<li>build(deps): bump ossf/scorecard-action from 2.4.1 to 2.4.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/96">go-viper/mapstructure#96</a></li>
<li>Update README.md by <a
href="https://github.com/peczenyj"><code>@​peczenyj</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/90">go-viper/mapstructure#90</a></li>
<li>Add omitzero tag. by <a
href="https://github.com/Crystalix007"><code>@​Crystalix007</code></a>
in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/98">go-viper/mapstructure#98</a></li>
<li>Use error structs instead of duplicated strings by <a
href="https://github.com/m1k1o"><code>@​m1k1o</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/102">go-viper/mapstructure#102</a></li>
<li>build(deps): bump github/codeql-action from 3.28.19 to 3.29.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/101">go-viper/mapstructure#101</a></li>
<li>feat: add common error interface by <a
href="https://github.com/sagikazarmark"><code>@​sagikazarmark</code></a>
in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/105">go-viper/mapstructure#105</a></li>
<li>update linter by <a
href="https://github.com/sagikazarmark"><code>@​sagikazarmark</code></a>
in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/106">go-viper/mapstructure#106</a></li>
<li>Feature allow unset pointer by <a
href="https://github.com/rostislaved"><code>@​rostislaved</code></a> in
<a
href="https://redirect.github.com/go-viper/mapstructure/pull/80">go-viper/mapstructure#80</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/tklauser"><code>@​tklauser</code></a>
made their first contribution in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/85">go-viper/mapstructure#85</a></li>
<li><a href="https://github.com/peczenyj"><code>@​peczenyj</code></a>
made their first contribution in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/90">go-viper/mapstructure#90</a></li>
<li><a
href="https://github.com/Crystalix007"><code>@​Crystalix007</code></a>
made their first contribution in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/98">go-viper/mapstructure#98</a></li>
<li><a
href="https://github.com/rostislaved"><code>@​rostislaved</code></a>
made their first contribution in <a
href="https://redirect.github.com/go-viper/mapstructure/pull/80">go-viper/mapstructure#80</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0">https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="8c61ec1924"><code>8c61ec1</code></a>
Merge pull request <a
href="https://redirect.github.com/go-viper/mapstructure/issues/80">#80</a>
from rostislaved/feature-allow-unset-pointer</li>
<li><a
href="df765f469a"><code>df765f4</code></a>
Merge pull request <a
href="https://redirect.github.com/go-viper/mapstructure/issues/106">#106</a>
from go-viper/update-linter</li>
<li><a
href="5f34b05aa1"><code>5f34b05</code></a>
update linter</li>
<li><a
href="36de1e1d74"><code>36de1e1</code></a>
Merge pull request <a
href="https://redirect.github.com/go-viper/mapstructure/issues/105">#105</a>
from go-viper/error-refactor</li>
<li><a
href="6a283a390e"><code>6a283a3</code></a>
chore: update error type doc</li>
<li><a
href="599cb73236"><code>599cb73</code></a>
Merge pull request <a
href="https://redirect.github.com/go-viper/mapstructure/issues/101">#101</a>
from go-viper/dependabot/github_actions/github/codeql...</li>
<li><a
href="ed3f921815"><code>ed3f921</code></a>
feat: remove value from error messages</li>
<li><a
href="a3f8b227dc"><code>a3f8b22</code></a>
revert: error message change</li>
<li><a
href="9661f6d07c"><code>9661f6d</code></a>
feat: add common error interface</li>
<li><a
href="f12f6c76fe"><code>f12f6c7</code></a>
Merge pull request <a
href="https://redirect.github.com/go-viper/mapstructure/issues/102">#102</a>
from m1k1o/prettify-errors2</li>
<li>Additional commits viewable in <a
href="https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/go-viper/mapstructure/v2&package-manager=go_modules&previous-version=2.2.1&new-version=2.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/VictoriaMetrics/VictoriaMetrics/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 12:59:21 +02:00
Olexandr88
aa342cea3b docs: add a link to the main, twitter, reddit icon (#9331)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-07-01 12:55:00 +02:00
Roman Khavronenko
26a2f4c25c deployment/docker: add troubleshooting section (#9329)
Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9323

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: Max Kotliar <mkotlyar@victoriametrics.com>
2025-07-01 12:53:02 +02:00
Andrii Chubatiuk
8a3a5e6867 app/vmalert: removed inline styles from UI, which are not working with recommended CSP (#9295)
fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9236

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-07-01 12:50:49 +02:00
Phuong Le
9f9a1e1996 document/data-ingestion/journald: fix small typo (#9325)
s/`-journlad.streamFields`/`-journald.streamFields`
2025-07-01 10:46:05 +02:00
Roman Khavronenko
2d27404639 app/vmselect/promql: respect window interval for rollup functions when removing resets (#9273)
removeCounterResets was operating only using stalenessInterval (when set
by user) and didn't account for user-specified [window] in rollup
functions. Since in rollup functions MetricsQL could look behind for up
to [window] interval - it can capture those datapoints that weren't
accounted in removeCounterResets. With this change, we remove resets on
stalenessInterval+window interval to avoid this corner case.

Fixes
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8935#issuecomment-2978728661

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-07-01 10:17:39 +02:00
Nils K
91a05697fd docs: Update journald ingestion docs regarding suggested fields (#9275)
### Describe Your Changes

Point out a some things to watch out for with the default stream field
set and explain what the `_TRANSPORT` field is useful for

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

Signed-off-by: Septatrix <24257556+septatrix@users.noreply.github.com>
2025-07-01 10:14:01 +02:00
hagen1778
e9571576b8 docs: add alias for vlogs keyConcepts page
GA noticed requests to /victorialogs/keyConcepts/ not being served properly

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-07-01 10:11:58 +02:00
Nikolay
314fed78cc app/vmagent: introduce concurrency setting for kafka producer (#906)
This commit adds a new option `concurrency` for kafka producer, which adds additional workers
for publishing messages into the kafka cluster.

 This setting could be useful at networks with high latency. And it increases write throughput.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9249
2025-06-30 18:21:47 +02:00
f41gh7
6751e43975 app/vmselect/promql: support search.logSlowQueryStatsHeaders for whitelisting header keys
Headers sent together with queries could contain important information
about the source of the request. This could help to find sources that send specific queries.

Logging all headers could expose sensitive info in logs.

So introducing `-search.logSlowQueryStatsHeaders` to whitelist headers that need
to be logged. See test case for example.
2025-06-30 18:21:39 +02:00
Andrii Chubatiuk
aaefe469c1 app/vmselect: proxy /api/v1/notifiers requests to vmalert (#9267)
Proxy /api/v1/notifiers requests to vmalert in the same manner, how it's done for other vmalert endpoints

Related to https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9267
2025-06-30 17:48:41 +02:00
Andrii Chubatiuk
fc33411d87 lib/awsapi: fixed static AWS credentials precedence
Previously lib/awsapi used incorrect precedence of authorization methods.

 This commit aligns this behaviour  with aws-sdk.

 Also, it fixes usage of `AWS_ROLE_ARN` env variable. It can only be used with web identity file and it must be ignored for any other configurations. 32873b942d/config/resolve_credentials.go (L121)

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9168
2025-06-30 17:47:02 +02:00
Nikolay
07574bdf7f lib/storage: properly optimise .+|^$ regex
Previously, regex `.+|^$` was optimised into `.+`. But in fact, it must
optimised into `.*`. Since this regex matches any non empty symbols and
empty value. Which combines into any input.

 This commit adds a special case of isDotStar check, which covers this
expression.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9290
2025-06-30 17:27:58 +02:00
Nikolay
e553a41fa0 app: add vlagent component
This commit introduces new component - VictoriaLogs Agent (vlagent).

It accepts logs data via any data ingestion protocol supported by
VictoriaLogs and forwards it to the provided remote storages.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8766
2025-06-30 17:01:05 +02:00
Alexander Frolov
f9aa74c367 lib/mergeset: misuse of unsafe.Pointer
It appears the `lib/mergeset.Item` violates the 3rd rule
https://pkg.go.dev/unsafe#Pointer

> (3) Conversion of a Pointer to a uintptr and back, with arithmetic.
> 
> Unlike in C, it is not valid to advance a pointer just beyond the end
of its original allocation:
> ```
> // INVALID: end points outside allocated space.
> b := make([]byte, n)`
> end = unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(n))
> ```


`CGO_ENABLED=0 go test -trimpath -gcflags=all=-d=checkptr -run
TestTableAddItemsSerial`
```
fatal error: checkptr: pointer arithmetic result points to invalid allocation


 This commit adds a special path to item encoding, that prevents invalid memory references.

 See this PR for details:
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9264
2025-06-30 16:56:28 +02:00
hagen1778
21878f0760 docs: mention vmui changes separately in vlogs and vm changelogs
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-30 15:02:38 +02:00
hagen1778
aca321f235 docs: add changelog after 71eef98b0e
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-30 14:56:20 +02:00
hagen1778
0b2e976706 dashboards: make dashboards-sync
follow-up after dc08b590c4

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-30 14:27:17 +02:00
Vadim Rutkovsky
dc08b590c4 dashboards: set equal heights for each row (#9298)
### Describe Your Changes
Several rows in cluster dashboard have 7 height, although the rest are 8
height. Setting all rows to 8 to be consistent


![Untitled](https://github.com/user-attachments/assets/16ba9601-9005-45f2-a01f-4b5fd59cd5b0)


### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

Depends on: #9253
2025-06-30 14:26:32 +02:00
Artur Minchukou
71eef98b0e app/vmui: add crossorigin attribute to manifest links
The change should solve the problem with loading manifest when vmui is behind reverse-proxy
with basic auth enabled.
2025-06-30 14:25:40 +02:00
Artem Navoiev
6bc48ce669 docs: enterprise - clarify FIPS builds (#9310)
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-06-30 14:24:20 +02:00
hagen1778
482ae8135f app/vmalert/notifier: follow-up a9b641531b
* reduce time wait on notifiers update
* deterministically sort notifiers() call. This improves and tests and output for users

a9b641531b
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-30 14:22:54 +02:00
Andrii Chubatiuk
393398996a docs/anomaly-detection: mark import_json_path as deprecated (#9283)
### Describe Your Changes

as noticed @f41gh7 in [operator
PR](https://github.com/VictoriaMetrics/operator/pull/1427#discussion_r2164171944)
vm writer `import_json_path` became deprecated starting
[v1.19.2](cc2cd0e084).
Adding this information to docs

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-27 15:51:53 +02:00
Mikhail
7703a95709 docs: fix typo in multi-region setup guide (#9297)
### Describe Your Changes

Just a typo correction in docs
2025-06-27 15:51:26 +02:00
Max Kotliar
114d657670 docs/victoriametrics/changelog: Add changelog for merged PR "Log errors during cache restore from file" (#9296)
### Describe Your Changes

Follow up on
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8952

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-27 15:49:56 +02:00
Hui Wang
a9b641531b vmalert: fix duplicated metrics for dynamically discovered notifier… (#9285)
…s via Consul and DNS

fix https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9260.

Bug was introduced in
[v1.114.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.114.0).
2025-06-27 15:49:10 +02:00
hagen1778
536df52682 dashboards: warn about correlation betweem concurrent requests and mem usage in panel description
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-27 11:36:05 +02:00
Zakhar Bessarab
5143ad7674 lib/backup/s3remote: retry ExpiredToken errors (#9286)
Tolerate token expiration as it might be handled ty token rotation
automatically when using automatic token rotation with EKS Pod Identity
and similar options.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9280

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
Co-authored-by: Max Kotliar <kotlyar.maksim@gmail.com>
2025-06-27 13:06:55 +04:00
Roman Khavronenko
6e7df578c4 app/vmctl: print import error before pipe error (#9288)
See
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9220#issuecomment-3001880833:
```
2025-06-24T17:27:47.062Z      error VictoriaMetrics/app/vmctl/backoff/backoff.go:60 got error: failed to write into "http://vminsert-vmcluster.metrics.svc.cluster.local:8480/insert/0/prometheus": io: read/write on closed pipe on attempt: 1; will retry in 2s
```

This error could happen only if pipe-reader was closed before we tried
to write into pipe-writer. But in this case we won't see the error
explaining why pipe-reader was closed. In this change, we checking if
there was a pipe-reader error before checking pipe-writer error.

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-27 09:23:12 +02:00
hagen1778
4a7b4ae852 docs: whitelist /admin/ requests in vmauth config for cluster VM
Besides `/select/`-prefixed requests vmauth also does `/admin/` requests
to fetch tenant IDs. Without whitelisting, such requests will fail to route.

I am adding this change only to generic vmauth configs where /admin/ access
is expected to be by default.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-27 09:18:54 +02:00
Jose Gómez-Sellés
65087f08c4 Migrate docs to cloud repo (#9230)
This is ready, since https://github.com/VictoriaMetrics/cloud/pull/3229
is merged .

This PR deletes the cloud docs folder after moving it into the private
cloud repo. The main reason is to keep things tidy and handle reviews in
a better way, as the helm charts repo is doing.

Future updates should be protected since the github actions file with
rsync command should not be messing with this folder when updating
everything.

### Checklist

The following checks are **mandatory**:

- [X] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-26 12:55:25 +02:00
Artur Minchukou
ca0479fff3 app/vmui/logs: update the color of the VictoriaLogs favicon to make the color different from VictoriaMetrics (#9270)
### Describe Your Changes

Updated the favicon color for Victoria Logs that the icon could be
distinguished from Victoria Metrics. Took the same color as in
victorialogs-datasource plugin.

![image](https://github.com/user-attachments/assets/521fc747-8ea7-43c7-a719-5434fe39ab06)


### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-26 10:39:15 +02:00
Yury Molodov
644c7a97c8 victorialogs/docs: fix invalid stats example in "Comments" section (#9272)
### Describe Your Changes

The example in the VictoriaLogs docs (Comments section) is currently
missing an aggregate function in the `stats` pipe:

```logsql
error                       # find logs with `error` word
  | stats by (_stream) logs # then count the number of logs per `_stream` label
  | sort by (logs) desc     # then sort by the found logs in descending order
  | limit 5                 # and show top 5 streams with the biggest number of logs
```

However, `stats by (_stream) logs` is invalid syntax - `logs` is
interpreted as a function name, which causes a parsing error.

This fix replaces it with a valid version using `count()`:

```logsql
| stats by (_stream) count() as logs
```

Without `count()`, the query fails with:

```
 cannot parse 'stats' pipe: unknown stats func "logs"
```

Signed-off-by: Yury Molodov <yurymolodov@gmail.com>
2025-06-26 10:34:57 +02:00
Roman Khavronenko
098cba5b73 dashboards: fix adhoc filters for vmalert and vmagent (#9271)
Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8657

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-26 10:33:55 +02:00
Hui Wang
5d0e8c0d1b vmalert: fix data race in replay ut (#9278)
see https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9265
2025-06-26 15:15:35 +08:00
Aliaksandr Valialkin
442bfa6c35 lib/logstorage: add tests, which verify that NaN and Inf values cannot be parsed by tryParseFloat64
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8474
2025-06-25 23:00:56 +02:00
Aliaksandr Valialkin
ee031b21a7 docs/victorialogs/LogsQL.md: document that sum() and avg() returns NaN when all the field values are non-numeric
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8474
2025-06-25 22:51:42 +02:00
hagen1778
deec361a64 lib/prombpmarshal: make linter happy
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-24 22:06:45 +02:00
Roman Khavronenko
fd4dce81ce lib/prombp{marshal}: support metadata in remote write protocol (#9124)
This change adds support for parsing and sending Metadata field in
Prometheus Remote Write protocol. It implements the first step for
Metadata support.

See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2974

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-24 22:00:34 +02:00
hagen1778
5431696d83 docs: fix various typos and grammar errors
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-24 21:45:55 +02:00
hagen1778
1b71184bfb docs: fix unresolved link in cluster docs
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-24 21:39:35 +02:00
Phuong Le
29c06b9543 VictoriaLogs: add a High Availability section to the cluster documentation. (#9247) 2025-06-24 18:53:24 +02:00
hagen1778
369f3f0da1 docs: rm integrations section from single-node readme
* move netdata and carbon-api integrations to a dedicated `Integrations` page
* drop https://github.com/aorfanos/vmalert-cli as it seems stale

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-24 16:58:56 +02:00
hagen1778
6f93f0e1a7 docs: minor typo fix
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-24 16:51:29 +02:00
Roman Khavronenko
96b773198f docs: update vmctl docs (#9257)
* split migration mods in separate sub-section. This removes conflicting
#-anchors and makes it easier to read&modify in future
* remove duplicating wording
* simplify texts

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8964

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-24 16:48:13 +02:00
Andrii Chubatiuk
006381266b app/vmalert: add /api/v1/notifiers endpoint and datasource_type query argument filter for /api/v1/rules and /api/v1/alerts endpoints (#9046)
### Describe Your Changes

added /api/v1/notifiers endpoint and `datasource_type` query argument
for `/api/v1/rules` and `/api/v1/alerts` API endpoints to filter groups
and rules by datasource type. required for
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8989

fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8537

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-06-24 16:41:38 +02:00
Max Kotliar
ae1dffe5d3 deployment/docker: Update grafana image version due to CVE issue (#9258)
### Describe Your Changes

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9207

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-24 16:31:53 +02:00
Nikolay
80e508eac7 lib/promscrape: remove duplicate targets from service-discovery
Previously, if annotation was update on object, it could result into
duplicate targets register for dropped targets service-discovery page.

 Mostly it affects endpoint annotations update. Endpoint holds
annotation with last update time. If any pod that belongs to the given
annotation changed, it causes duplication targets for all pod backed by
the endpoint. It makes service-discovery debug page hard to use.

 This commit excludes `__metadata_kubernetes_*_annotation_` from key
generation for dropped targets map. Instead it updates target with new
labels value.

  It may lead to some targets collision, but
since hash function already could produce collisions, it should not be a
problem.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8626
2025-06-24 11:32:29 +02:00
f41gh7
86d8095417 docs: mention v1.120.0 release
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-06-23 16:36:30 +02:00
f41gh7
df847e62c0 docs: mention new LTS releases
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-06-23 16:32:35 +02:00
Aliaksandr Valialkin
1e3791cbf6 lib/storage: move testing/synctest usage into separate files ending with _synctest_test.go
The files with synctest usage are built only if the goexperiment.synctest build tag is set.
This allows running `go test ./lib/...` and `go vet ./lib/...` without the need to pass GOEXPERIMENT=synctest to them.

This is a follow-up for d33d7e20be
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8848
2025-06-21 12:27:22 +02:00
Aliaksandr Valialkin
b1f3d7f3eb app/vlinsert/journald: add a benchark for the isValidFieldName() function 2025-06-21 12:15:45 +02:00
Aliaksandr Valialkin
c2c6f97bd3 lib/fasttime: remove performance overhead when UnixTimestamp() is called from benchmark loops
Move the synctest-related implementation into a separate file protected with go:build goexperiment.synctest.

This is a follow-up for the commit 06c26315df
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8740
2025-06-21 12:09:55 +02:00
Aliaksandr Valialkin
274e38ebee docs/victorialogs/data-ingestion/Journald.md: mention that _TRANSPORT and _SYSTEMD_USER_UNIT fields are also good candidates for log streams
Thanks to @septatrix for the suggestion at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9143#issuecomment-2983752442
2025-06-20 23:26:16 +02:00
Aliaksandr Valialkin
e05738749c docs/victorialogs/CHANGELOG.md: typo fixes in links to stats functions 2025-06-20 22:25:57 +02:00
Aliaksandr Valialkin
3428d0d27d deployment: update VictoriaLogs Docker image tags from v1.23.3-victorialogs to v1.24.0-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.24.0-victorialogs
2025-06-20 21:29:54 +02:00
Aliaksandr Valialkin
f8170b2471 docs/victorialogs/CHANGELOG.md: cut v1.24.0-victorialogs 2025-06-20 21:20:35 +02:00
Aliaksandr Valialkin
57925c34e6 app/vlselect/vmui: run make vmui-logs-update after 9e60fc8fc8 2025-06-20 21:19:07 +02:00
Artur Minchukou
9e60fc8fc8 app/vmui/logs: move compact mode of VictoriaLogs table to separate tab (#8745)
### Describe Your Changes

Related issue: #7047 and #8438

- removed compact mode of VictoriaLogs table
- added sorting by field to JSON tab 

![image](https://github.com/user-attachments/assets/c02bbbed-cf2c-41e3-86fe-97bc205654a5)
- added sorting of field names to JSON tab


### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-06-20 17:26:28 +02:00
f41gh7
07c8a4a9a7 make vmui-update 2025-06-20 17:04:17 +02:00
f41gh7
e098ef901f CHANGELOG.md: cut v1.120.0 release 2025-06-20 16:41:00 +02:00
f41gh7
7693c4bcce docker/Makefile: add EXTRA_TAG_SUFFIX variable to buildx publish
New variable should help to change docker image tag name during release prepare.

Instead of publishing an exact version, like v1.1.0, it should use suffixed version v1.1.0-rc1.
Which should be re-tagged later, when release will be promoted to stable.

Related to https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9136

Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-06-20 16:39:27 +02:00
Fred Navruzov
8bb56f8ef5 docs/vmanomaly: release v1.24.1 (#9241)
### Describe Your Changes

Patch release doc updates for vmanomaly (v1.24.1)

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-20 16:35:02 +02:00
Alexander Frolov
b91d249a29 lib/httpserver: option for disabling HTTP keep-alives (#9125)
### Describe Your Changes

Some network configurations may not work optimally with long-lived
connections. \
Address the issue described by #2395 for other components.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: Aleksandr Frolov <fxrlv@nebius.com>
Co-authored-by: Aliaksandr Valialkin <valyala@gmail.com>
Co-authored-by: Max Kotliar <kotlyar.maksim@gmail.com>
Co-authored-by: Roman Khavronenko <hagen1778@gmail.com>
Co-authored-by: Roman Khavronenko <roman@victoriametrics.com>
2025-06-20 12:43:21 +02:00
Hui Wang
7b274e0d6d vmalert: correct the rule evaluation timestamp if the system clock is… (#9228)
… changed during runtime

Strip the monotonic clock with `t.Round(d)` or `t.Truncate(d)` before
apply `Sub()`, to force the wall clock usage which corrects the rule
evaluation timestamp if the system clock is changed during runtime.

fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8790

---------

Co-authored-by: Max Kotliar <kotlyar.maksim@gmail.com>
Co-authored-by: Roman Khavronenko <roman@victoriametrics.com>
2025-06-20 12:17:31 +02:00
Benjamin Nichols-Farquhar
b3c92540e5 vmalert: respect group.concurrency in replay mode (#9214)
### Describe Your Changes

Revival and modification of original PR
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8762 after
discussion on
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7387.

`group.concurrency` is now respected if and only if
`-replay.rulesDelay=0` rather than always. This allows rules to be run
concurrently without ambiguity about rule chaining. If
`-replay.rulesDelay` is set greater than zero concurrency is still
ignored. This will be the default behavior since it defaults to 1s.

Implementation considerations:

I chose to add split some simple logic into a helper function in
preparation for adding `replay.singleRuleEvaluationConcurrency` in a
follow up PR as thats we're we can share that logic.

cc @Haleygo 
### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Co-authored-by: Hui Wang <haley@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-06-20 12:14:18 +02:00
Artem Fetishev
0dd63a60d0 lib/storage: Change BenchmarkHeadPostingForMatchers to use global index time range explicitly (#9233)
During the data retrieval, VictoriaMetrics switches to global index
search if the time range is > 40 days. Prior
ba0d7dc2fc, this switch was handled in
indexDB code. That commit moved that logic to the storage level. As the
result, indexDB will search per-day index for whatever time range that
is passed to it.

This broke the BenchmarkHeadPostingForMatchers. It now shows very slow
indexDB performance compared to v1.111.0 (the last release before that
commit). This is because now indexDB tries to search 55 years of data by
spawning a separate goroutine for each day. Even though the data was
inserted only for the current day, running that many goroutines
significantly slows down the search.

The fix is to use global index time range explicitly.

Fixes #9203 

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-06-20 11:55:04 +02:00
Benjamin Nichols-Farquhar
32fc801519 vmstorage: add flag for storage metricName cache tuning (#9156)
Similar to other storage caches `storage/metricName` can be very
important to performance, however it is not tunable independently like
other caches.

In high cardinality setups where a large amount of that cardinality is
actively queried we can see a high `metricName` miss rate.

The only way to correct this is to increase available memory either by
provisioning more or by increasing `memory.allowedPercent`, which is
often expensive or undesirable for stability reasons.

Its possible to work around this by increasing `memory.allowedPercent`
and then adjusting `storage.cacheSizeIndexDBDataBlocks` and
`storage.cacheSizeStorageTSID` down as they are the largest caches, but
this is a less ideal solution than being able to directly control this
cache size.

Related to
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8843
2025-06-20 11:33:39 +02:00
Artem Fetishev
771f742842 lib/storage: extract adding metricIDs to the pendingHourEntries into a separate func (#9138)
This change has been requested to be done in a separate PR during the
partition index review. See:
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8134#discussion_r2131692079

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-06-20 09:58:11 +02:00
Max Kotliar
a845fe815a lib/logstorage: clarify comment on writeBlockResultFunc usage constraints (#9235)
### Describe Your Changes

The `DataBlock` contains structs with string fields, and while the
original comment mentioned not holding references to `br`, it wasn't
immediately clear that this also applies to fields like strings within
the data.

This change clarifies that the `writeBlockResultFunc` must not retain
references to any part of `br`, including its fields. This makes it
explicit that even seemingly safe types like strings must be copied if
needed.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-19 16:30:56 +02:00
Phuong Le
2eadd4c9f9 vlogs: fix inconsistent type for HTTP request duration metric (#9225)
The 'select' HTTP request duration metric is currently implemented as a
summary, while the 'insert' HTTP request duration uses a histogram.

All time series under the same metric name must use the same metric
type. Using the summary type for this metric is preferable, as it
significantly reduces the number of unique time series generated. While
summaries have the limitation of not supporting accurate aggregation
across multiple instances or paths, this trade-off is more manageable
than dealing with a high-cardinality explosion caused by histograms.
2025-06-19 14:49:29 +02:00
Aliaksandr Valialkin
eb7b088c91 lib/logstorage: provide standard string representation for all the priority and severity levels in Syslog and Journald protocols inside the "level" field
It is better from usability PoV to provide string representation for all the priority and severity levels
instead of merging some of them into a common groups.

This is requested at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9209
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8535
2025-06-19 14:39:20 +02:00
Aliaksandr Valialkin
19a50ae7cd app/vlinsert/journald: follow-up for 01d413873e
- Add more tests, which cover various edge cases for binary encoding of log field value in journald format
- Moved common code for reading the next line to fieldsBuf.value. This simplifies the code a bit.
- Added more comments, which try explaining the braindead logic for parsing binary-encoded log field values in journald format

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9070
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9153
2025-06-19 13:50:46 +02:00
Andrii Chubatiuk
01d413873e app/vlinsert/journald: fixed binary value parsing (#9234)
### Describe Your Changes

- removed unneeded loop for binary field value size extraction, since it
should not be delimited by multiple `\n` symbols
- changed loop condition

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-19 13:47:56 +02:00
Aliaksandr Valialkin
d307a64cd2 app/vlinsert: do not trim prefixes from "/insert/*" URL paths
This improves maintainability and readability of the code, since it simplifies searching
for the particular request handler by its' full path.
2025-06-19 08:46:57 +02:00
Artur Minchukou
27f1c1ab13 app/vmui/logs: fix missing field values in auto-complete (#8799)
### Describe Your Changes

Related issue: #8749 
Added query to requests `/field_names` and `/field_values` to get more
precision results:
 
- If `filterName` is `_msg` or `_stream_id`, the query cannot be
generated specifically,
    so a wildcard query (`"*"`) is returned.
 
- If `filterName` is `_stream`, the query is generated using regexp
(`{type=~"value.*"}`).
 
- If `filterName` is `_time`, a simplified query is created by trimming
the value up
    to the first occurrence of a delimiter such as `-` or `:`.
 
- For all other values of `filterName`, a prefix query is returned using
    the `query` value with a `*` appended (e.g., `"value*"`).

Related issue: #8806 
Enhanced autocomplete with parsed field suggestions from unpack pipe.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Co-authored-by: Nikolay <nik@victoriametrics.com>
Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
2025-06-19 01:10:45 +02:00
Artur Minchukou
60396d0daa app/vmui/logs: ensure the live tailing tab automatically reconnects on connection loss (#9162)
### Describe Your Changes

Related issue: #9129 

Added restarting the live tailing tab on connection loss

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
2025-06-19 01:08:11 +02:00
Yury Molodov
9b2c1b00cf vmui/logs: fix hits chart not updating on tenant change (#9171)
### Describe Your Changes

Adds `tenant` to the dependency array for log hits fetching to ensure
the chart updates when `AccountID` or `ProjectID` changes.
Related issue: #9157 

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

Signed-off-by: Yury Molodov <yurymolodov@gmail.com>
Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
2025-06-19 01:06:19 +02:00
Aliaksandr Valialkin
892008b05d docs/victorialogs/CHANGELOG.md: document dc2da9a71b
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9200
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9201
2025-06-19 01:02:56 +02:00
Vadim Alekseev
dc2da9a71b app/logstorage: optimize pipes after appending limit pipe (#9201)
### Describe Your Changes

This PR adds a call to optimize pipes after the `limit` pipe has been
appended.

Related: #9200

While this approach is not ideal, since it forces us to re-optimize all
pipes, but it is simpler.

An alternative would be to reapply only the relevant optimizations
specifically for this case, something like:

```go
func (q *Query) AddPipeLimit(n uint64) {
	if len(q.pipes) > 0 {
		ps, ok := q.pipes[len(q.pipes)-1].(*pipeSort)
		if ok {
			if ps.limit == 0 || n < ps.limit {
				ps.limit = n
			}
			return
		}
		pu, ok := q.pipes[len(q.pipes)-1].(*pipeUniq)
		if ok {
			if pu.limit == 0 || n < pu.limit {
				pu.limit = n
			}
			return
		}
	}
	q.pipes = append(q.pipes, &pipeLimit{
		limit: n,
	})
}
```

### Checklist

The following checks are **mandatory**:

- [X] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-19 00:57:24 +02:00
Artur Minchukou
5908ee1009 app/vmui/logs: improve usability of the live tailing tab (#9194)
### Describe Your Changes

Related issue: #9130 

- add `ScrollToTopButton` component for better navigation UX and
integrate it into Live Tailing view;
 
<img width="1293" alt="image"
src="https://github.com/user-attachments/assets/98a96ac8-fe2b-43fa-a470-a51f68df2e01"
/>

- replace log throttling logic with the new `LogFlowAnalyzer` utility
for enhanced performance state tracking;
- enhance `GroupLogsItem` with a copy-to-clipboard feature, which allows
to copy only one log object;
 
<img width="1268" alt="image"
src="https://github.com/user-attachments/assets/c42ad5e1-0d02-456e-b231-d42064f48eb4"
/>

 - update styles for better responsiveness and aesthetics;
- change raw json view into expandable view in the live tailing tab by
default and keep the value of this setting in the local storage, it
became possible thanks to [this
issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9130#9083).
  
<img width="554" alt="image"
src="https://github.com/user-attachments/assets/6bcda0f1-dd2f-4608-8e0d-f9c0bc6efac3"
/>



Short demo: 


https://github.com/user-attachments/assets/351133a7-f3ef-41ad-b23d-cc12f030a357


### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-19 00:54:50 +02:00
Nikolay
c930a81ea9 app/vlinsert: remove vlstorage dependency for vlinsert (#9221)
vlinsert package could be used as an imported dependency. Mostly it's
needed for vlagent, but it could be a case for other applications.

 This commit introduces new interface for vlinsertutil package, which
represents actual storage for log rows ingestion.

 It includes CanWriteData, which also could be used to introduce
 back-pressure mechanism for vlinsert clients.

Related PR: https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9034

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
2025-06-19 00:33:04 +02:00
Nikolay
c95990f47f lib/logstorage: properly iterate over ForEachRow (#9222)
Previously, ForEachRow always reset last row fields after iteration.
It makes impossible concurrent iteration with forEachRow, since
ForEachRow performed hidden mutation of LogRows.

 This commit resolves this issue by removal of fields reference.

Related to
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9076
2025-06-19 00:24:50 +02:00
Aliaksandr Valialkin
f0442e40a0 lib/logstorage: follow-up for 5d06c74e2b
Move the lex.isQuotedToken() check to the top of the lexer.isInvalidQuotedString() function
in order to simplify understanding the code.

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9167
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9219
2025-06-19 00:19:17 +02:00
Andrii Chubatiuk
5d06c74e2b lib/logstorage: fix panic when not paired quotes are passed as a pipe value (#9219)
### Describe Your Changes

nextToken method, which is called prior to getCompoundTokenExt already
unquotes string, paired quotes check inside getCompoundTokenExt is
redundant
fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9167

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
2025-06-19 00:15:44 +02:00
Aliaksandr Valialkin
63dccea932 app/vlinsert/journald: parse journald logs in streaming manner
This allows parsing unlimited number of logs in a single HTTP request,
without the need to buffer the logs in memory.

This is needed for https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9070

Thanks to @AndrewChubatiuk for the initial pull request - https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9153

This commit is based on the https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9153 .
It contains the following changes comparing to the original pull request:

- Remove ugly function LineReader.NextLineWithLineFn(). Instead, uglify the Journald parser a bit
  with hacky calls to LineReader.NextLine() in order to parse binary-encoded field values.
  This should preserve the maintainability of the LineReader, which is shared among multiple protocol parsers,
  under control, while keeping the complexity of Journald parsing inside the app/vlinsert/journald package.

- Fix a typo bug inside isNameValid() - `(r < '0' && r > '9')` must be written as `(r < '0' || r > '9')`.
  Rewrite isNameValid() into easier to understand code and rename it to isValidJournaldFieldName() for better readability.
  Add tests for this function.

- Remove mentioning of the -journald.maxRequestSize command-line flag from VictoriaLogs docs.

- Add the description of the fix to VictoriaLogs changelog.

- Properly increment errorsTotal metric on every journald parse error.

- Add missing protoparserutil.PutUncompressedReader(reader) call, so the reader could be re-used between client requests.

- Remove improperly working code, which tries continuing parsing the request stream after parse errors.
  It is impossible to recover reliably from journald parse errors related to reading the data from the request stream,
  since the journald protocol format is completely braindead. So it is better to immediately return the error
  to the client instead of trying to recover. The only errors, which could be recovered, are related to invalid field names / values.
  Such errors are logged with the WARN level and the corresponding fields are skipped.

- Fix incorrect storage of the re-used name and value strings into fb.fields. The contents of the name and value strings
  must be copied per every loop, which reads these strings from the request stream. Otherwise the contents of the previously
  added Name and Value fields into fb.fields will be overwritten on the next loop.

- Ensure that LineReader.Line is set to nil after LineReader.NextLine() returns false. This should prevent from subtle bugs
  when the LineReader.Line is read after LineReader.NextLine() returns false.
2025-06-18 23:48:22 +02:00
Fred Navruzov
46acf8edc0 docs/vmanomaly: release 1.24.0 post-release updates (#9224)
### Describe Your Changes

Fixing typos and missing links after v1.24.0 doc update in #9191 

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-18 23:29:54 +02:00
Fred Navruzov
d478d1496a Docs: vmanomaly release v1.24.0 (#9191)
### Describe Your Changes

> ⚠️  still draft, don't merge even if already approved

Docs update for vmanomaly v1.24.0 release with stateful service option

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-18 22:41:59 +02:00
Aliaksandr Valialkin
272a77a9c3 lib/logstorage: optimize OR filters where one of these filters is *
Such filters can be optimized to `*`. This avoid executing other OR filters.
For example, `foo or * or bar` is optimized to `*`, while `foo` and `bar` filters aren't executed.

Such filters are frequently generated by Grafana, so this should improve query performance there.
2025-06-18 16:53:35 +02:00
Aliaksandr Valialkin
e72a3fdb67 lib/logstorage: properly parse unquoted regexp filters ending with *
Use getCompoundToken() instead of getCompoundFuncArg() for obtaining regexp filter value,
since getCompoundFuncArg() skips trailing '*' chars.

This allows detecting invalid queries in the https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8582 .
2025-06-18 16:53:34 +02:00
Zakhar Bessarab
7413000e57 docs/changelog: add link to an issue after 971c759a
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-18 18:06:32 +04:00
Roman Khavronenko
ddd686c026 app/vmalert: rename samples to series (#9204)
`Samples` could be confusing for users, especially for alerting rules:
* we say in docs that each returned "series" will create a new alert
* we say that there are "series fetched", so both columns should be
either "series" or "samples".

Let's rename it to `series` for consistency.

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-18 14:50:24 +02:00
Hui Wang
0e8007a02b vmalert: do not break vmalert process under replay mode when rule use… (#9206)
…s `query` template, but only logging a warning

The `query` template is not supported in replay mode, because we perform
range queries on the rule’s expression, but not on the `query` template.
Previously, if user see error `query template isn't supported in replay
mode`, they need remove the `query` template from the rule for replay
mode.
Also, templating is only used for alerting rules. Replaying alerting
rules don't send notifications(rule annotations are included here) and
users mainly focus on the generated `ALERTS`, the `query` result is
trivial. This pull request shouldn't break things but simplifies the
usage of replay mode for the case.

related https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8746
2025-06-18 14:23:12 +02:00
Dmytro Kozlov
cbd76ac4dc docs/vmctl: add information about the prometheus snapshot folder structure (#9208)
### Describe Your Changes

Users try to migrate from systems like Thanos or Prometheus using
`vmctl` and `promtheus` migration protocol, with questions about the
problems when they try to specify the snapshot, but `vmctl` shows `0`
series to be found for migration.
This issue happens because users specify the block folder instead of the
snapshot folder.
Added clarification about snapshot structure and its appearance with
multiple blocks inside.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-18 14:22:42 +02:00
Andrii Chubatiuk
96b8213b0d lib/streamaggr: fixed rate_avg and rate_sum when scrape interval is bigger than aggregation interval (#9170)
### Describe Your Changes

fixes #9017
additionally introduced testing/synctest library to cover this and cases
from previous releases related to aggregation windows and panics in
outputs with state

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-06-18 14:19:51 +02:00
Zakhar Bessarab
971c759acc packaging/make: fix archiving release binaries for cluster (#903)
* packaging/make: fix archiving release binaries for cluster

Cluster binaries for non-windows platforms did not include fips binaries, fix that by properly including binaries.

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-18 16:06:14 +04:00
Phuong Le
01a7ab8bf4 vlinsert/journald: fix timestamp parsing when using default time field (#9150)
See #9144 

VictoriaLogs was not correctly parsing timestamps from journald data
when using the default time field configuration. This caused
VictoriaLogs to look for a `_time` field instead of
`__REALTIME_TIMESTAMP` in journald data by default, resulting in
timestamps falling back to ingestion time rather than the actual log
timestamps.

Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
2025-06-18 12:59:46 +02:00
Aliaksandr Valialkin
d29bb97fec docs/victorialogs/CHANGELOG.md: move the BUGFIX entry to the correct place after the commit 9b21dc5a30
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9062
2025-06-18 12:37:37 +02:00
Aliaksandr Valialkin
48554d51b9 app/vlinsert/journald: properly read timestamp from __REALTIME_TIMESTAMP field by default
The CommonParams.TimeFields is initialized to []{"_time"} by default. This prevent from the proper usage of the -journald.timeField
as the default field for reading log timestamps.

This bug has been introduced in the commit a1a731eb61

While at it, make sure that every parsed log entry has its own timestamp if the timestamp couldn't be read from the log entry.
This provides reliable sort order of the log fields.
2025-06-18 12:36:02 +02:00
Aliaksandr Valialkin
105a42ce08 app/vlinsert/journald: use (_MACHINE_ID, _HOSTNAME, _SYSTEMD_UNIT) as default log stream fields for logs ingested via journald data ingestion protocol
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9143
2025-06-18 12:03:21 +02:00
Will Sargent
8b58dc1892 deployment/docker/victorialogs: Fix container name to fluentbit-oltp (#9213)
### Describe Your Changes

The container name for oltp has the same name as the loki container.
Fixed.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-18 11:57:20 +04:00
Aliaksandr Valialkin
d9064dc781 docs/victorialogs: document facility_keyword field, which is automatically added by Syslog parser
The facility_keyword field has been added in the commit ff9cb3f821
2025-06-17 10:56:47 +02:00
Aliaksandr Valialkin
ff9cb3f821 app/vlinsert: use string representation of log level at logs ingested into VictoriaLogs via syslog and journald protocols
It is better from usability PoV to use string representation for the 'level' log field
instead of numeric representation.

Remove the -journald.priorityAsLevel and -syslog.severityAsLevel command-line flags,
since there are zero practical reasons when the `level` log field shouldn't be initialized automatically.

Move the CHANGELOG description for this feature into the correct place at docs/victorialogs/CHANGELOG.md,
and make it more human-readable.

Document the 'level' log field at https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/
and at https://docs.victoriametrics.com/victorialogs/data-ingestion/journald/

This is a follow-up for 50969ca780

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8535
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8553
2025-06-17 10:49:23 +02:00
Andrii Chubatiuk
50969ca780 app/vlinsert: introduced flags, that enable syslog severity and journald priority fields casting to a level field (#8553)
### Describe Your Changes

fixes #8535 

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-06-17 08:29:17 +02:00
Zakhar Bessarab
195afd1c2e app/vmbackupmanager: increase storage healthcheck duration (#902)
Storage node with large number of partitions (e.g. 150+ partitions with 12Tb of data) will take more than 30 seconds to start. This was causing vmbackupmanager restarts when running vmstorage colocated with vmbackupmanager in a single pod.

Use exponential backoff for retries and increase overall timeout for storage node healthcheck to 3 minutes to avoid vmbackupmanager restarts during storage node startup.

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-16 17:50:51 +04:00
Zakhar Bessarab
c5743a7099 lib/backup/azremote: do not use SAS token for copying objects (#9172)
Using SAS token is not required when copying data within a single
storage account. Using a plain object URL is sufficient for this case. A
single storage account is normally used to store backups so it is safe
to remove SAS tokens usage.

This fixes support of server-side copy when using managed identity as
authentication source as SAS token can only be generated when using
"shared key" type of credentials.

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9131

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-16 11:30:16 +04:00
Dmytro Kozlov
ac11f184fc apptest/vmctl: implement integration tests for the remote read protocol (#9164)
Implemented integration tests for the remote read protocol (for both mode stream and default).
Removed old implementation from the vmctl. 

Related issue
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7700

Co-authored-by: Artem Fetishev <149964189+rtm0@users.noreply.github.com>
2025-06-16 07:09:08 +02:00
Andrii Chubatiuk
973eb1cc4f apptest: validate relabelling after reload (#9175)
Related issue https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8946

Co-authored-by: Max Kotliar <mkotlyar@victoriametrics.com>
2025-06-13 14:35:50 +02:00
hagen1778
3382bbf285 dashboards: set Y-min and units for re-processing panel
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-13 13:53:02 +02:00
Fred Navruzov
5ec7cc5dd4 docs/vmanomaly: release 1.23.3 (#9180)
### Describe Your Changes

Docs update to vmanomaly v1.23.3

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-13 10:17:16 +02:00
Nick Yang
9b21dc5a30 app/vlinsert: support - timestamp for rsyslog
rfc5424 allows for `-` for timestamps when the syslog application cannot
get the current time (e.g., embedded devices that have not yet NTP'd),
and the log ingester should apply its timestamp in that case

RFC5424:
https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.3

Related PR:
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9062
2025-06-11 14:20:06 +02:00
Roman Khavronenko
e828f03eaa app/vmselect/promql: add rate_prometheus
support
[rate_prometheus](https://docs.victoriametrics.com/victoriametrics/metricsql/#rate_prometheus)
function, an equivalent to `increase_prometheus(series_selector[d]) / d`

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8901
2025-06-11 14:15:02 +02:00
f41gh7
4dc9ca26fc vendor: update metricsql 2025-06-11 14:13:21 +02:00
Roman Khavronenko
63e1bf5d97 app/vmselect: respect staleness markers when calculating rate and increase functions
The new behavior will interrupt rate/increase calculation if last sample
on the selected time window is a staleness marker,
making the series to disappear immediately instead of slowly fading
away.

See more details in
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8891#issuecomment-2883119388.
2025-06-11 13:57:31 +02:00
Nikolay
d8b36fb2e3 apptest: add base test cases for victoria-logs
This commit adds key concepts and ingestion protocol tests for
victoria-logs component.
2025-06-11 13:56:13 +02:00
Phuong Le
aa3a2b01aa spellcheck: run 2025-06-11 13:54:16 +02:00
Max Kotliar
fd543883fa .github/workflows: allow codecov to report without failing CI build
### Describe Your Changes

The `fail_ci_if_error` flag only affects the upload step and does not
control
Codecov's status checks (e.g., codecov/patch, codecov/project). My prior
tests
did not surface this behavior.

Switched to 'informational' mode per Codecov docs to avoid blocking CI.
See:

https://docs.codecov.com/docs/common-recipe-list#set-non-blocking-status-checks

Tested in https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9146

Follow up on
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9139,
52022e482c
2025-06-11 13:47:51 +02:00
Dmytro Kozlov
bbf3ab099b apptest/vmctl: migrate vmctl test for the vm-native migration process (#9059)
Moved the migration process via the native protocol (vmsingle to
vmsingle) test to the apptest folder, where all integration tests are
held

Related issue
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7700

Co-authored-by: Artem Fetishev <rtm@victoriametrics.com>
2025-06-10 16:03:01 +02:00
Andrii Chubatiuk
fa68453e41 deployment/docker/victorialogs: fixed journald ignore filters in example (#9154)
### Describe Your Changes

removed trailing comma in ignoreFields, which led to _msg field removal,
since it is converted to empty string before filtering

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-10 13:54:23 +02:00
sforests
8f47e30c1d lib/storage:fix Less Method in tagFilter Struct (#9127)
### Describe Your Changes

This pull request addresses a bug in the Less method of the tagFilter
struct. The original implementation incorrectly assigned the value of
isCompositeB by calling tf.isComposite() instead of other.isComposite().
This caused both isCompositeA and isCompositeB to always have the same
value, leading to incorrect comparisons when determining the order of
tagFilter instances.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Co-authored-by: Zhu Jiekun <jiekun@victoriametrics.com>
2025-06-10 13:52:21 +02:00
Zakhar Bessarab
f66981cac1 docs/changelog: backport changes for 1.110.11
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-10 14:03:34 +04:00
hagen1778
780c67d139 dashboards: add panel Partitions scheduled for re-processing to VM cluster dashboard
It shows the amount of data scheduled for [downsampling](https://docs.victoriametrics.com/#downsampling)
 or [retention filters](https://docs.victoriametrics.com/#retention-filters).
 The new panel should help to correlate resource usage with background re-processing of partitions.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-10 09:30:17 +02:00
hagen1778
9244557b6e dashboards: use RSS anon memory in per-component sections
Anonymous RSS memory usage per component type is more useful to observe
for finding anomalies.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-10 09:12:35 +02:00
Aliaksandr Valialkin
ee940e81ec lib/logstorage: improve performance for isTokenChar() by using 256-byte lookup table
This increases performance for the isTokenChar() by up to 30%.

Thanks to @ahfuzhang for the initial idea at https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9064/files#diff-27b31ccad49a8ceaf033f97deb3d876d62eab4119374cbb3ae65278e894f6c69
2025-06-09 20:59:37 +02:00
Aliaksandr Valialkin
695532fc8d lib/logstorage: call isTokenChar() for ascii chars passed to isTokenRune()
This improves isTokenRune() performance for ascii chars by up to 30%.

Thanks to @ahfuzhang for the initial idea at https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9064/files#diff-27b31ccad49a8ceaf033f97deb3d876d62eab4119374cbb3ae65278e894f6c69
2025-06-09 20:59:37 +02:00
Aliaksandr Valialkin
ccb5b47914 lib/prompbmarshal: make size() private methods, since they arent used outside lib/prompbmarshal 2025-06-09 19:32:22 +02:00
Aliaksandr Valialkin
e0f3ecd073 lib/prompbmarshal: make marshalToSizedBuffer() private methods, since they arent used outside lib/prompbmarshal 2025-06-09 19:29:56 +02:00
Max Kotliar
646604d850 .github/workflows: allow codecov to report without failing CI build (#9139)
### Describe Your Changes

Currently, some PRs have a failed CI due to low code coverage reported
by Codecov. However, the team typically ignore this and relies on other
quality indicators such as thorough code reviews.

This change configures Codecov to continue posting coverage reports
without marking the build as failed.

It also helps reduce confusion for external contributors, who might
otherwise feel pressured to add unnecessary tests just to satisfy
Codecov requirements (for example
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9002#discussion_r2111651046).

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-09 17:51:23 +02:00
Zakhar Bessarab
0e6b3eabb5 docs/release-guide: fix link to release follow-up
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-09 16:00:24 +04:00
Zakhar Bessarab
7165820b6a docs: update version of VictoriaMetrics components to v1.119.0
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-09 15:56:30 +04:00
Zakhar Bessarab
d233170ada deployment/docker: update versions of VictoriaMetrics components to v1.119.0
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-09 15:53:18 +04:00
Zakhar Bessarab
c7f2d91d08 docs/victoriametrics/changelog: backport LTS changelog
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-09 15:13:42 +04:00
Artem Fetishev
7f5a8af464 apptest: Add basic backup/restore integration test (#9133)
This commit adds a basic backup/restore test for vmsingle and vmcluster. A
more sophisticated was originally added to the partition index PR
(#8134) and was aimed to test backup/restore when switching back and
forth between legacy and partition index. During the code review it was
decided that it would be good to have a separate test as well since
legacy code will be removed in future and so will the test.

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-06-09 12:17:54 +02:00
Fred Navruzov
181a465c89 docs/vmanomaly: release v1.23.2 (#9135)
### Describe Your Changes

Update docs to vmanomaly release v1.23.2

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-09 11:28:56 +02:00
Fred Navruzov
7288adab21 docs/vmanomaly: release v1.23.1 (#9132)
### Describe Your Changes

Update the docs to release v1.23.1

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-08 23:07:02 +02:00
Aliaksandr Valialkin
993a9d92d6 deployment/docker/builder/Dockerfile: download musl archives for cross-compilation from the local repository instead of musl.cc
This speeds up building the Go builder image significantly (from hours to a few minutes),
since the build speed was limited by the download speed from https://musl.cc , and this speed
was extremely slow (e.g. 10kb/s and slower).

This also improves build security, since the local mirror of musl.cc is under our control.
2025-06-08 13:47:13 +02:00
Aliaksandr Valialkin
45c889a1cf docs/victorialogs/querying/README.md: mention that web UI supports live tailing
This is a follow-up for the commit 231bfcf4cf

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8882
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7046
2025-06-08 09:12:54 +02:00
Aliaksandr Valialkin
dca5d44f2b deployment: update base Docker image from alpine:3.21.3 to alpine:3.22.0
See https://alpinelinux.org/posts/Alpine-3.22.0-released.html
2025-06-08 08:08:16 +02:00
Aliaksandr Valialkin
9e4f0cc900 go.mod: update Go from 1.24.3 to 1.24.4
See https://github.com/golang/go/issues?q=milestone%3AGo1.24.4+label%3ACherryPickApproved

This is a follow-up for 54dc9cc322
2025-06-08 08:03:03 +02:00
Aliaksandr Valialkin
54dc9cc322 deployment: update Go builder from Go1.24.3 to Go1.24.4
See https://github.com/golang/go/issues?q=milestone%3AGo1.24.4+label%3ACherryPickApproved
2025-06-08 08:01:45 +02:00
Aliaksandr Valialkin
67e6752b82 docs/victoriametrics/goals.md: clarify the main goal 2025-06-08 07:57:54 +02:00
Zakhar Bessarab
bb54075c23 docs/victoriametrics/changelog: cut v1.119.0
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-06 16:48:02 +04:00
Zakhar Bessarab
08f5220bc3 app/{vmselect,vlselect}: run make vmui-update vmui-logs-update
Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-06 16:38:04 +04:00
DmitrySafonov
f9015da6eb app/promql/rollup_result_cache: include extra_filters in rollupCache key for multi-tenant support
This PR addresses two issues:

When tenant labels (e.g. vm_account_id, vm_project_id) are passed via
extra_filters, they were not included in the rollupCache key. This could
cause cache entries to be reused across different tenants, resulting in
incorrect query results.
If a tenant is specified only via extra_filters, and that tenant does
not exist in TenantsCached, it gets silently filtered out by
GetTenantTokensFromFilters, causing the query to fall back to a global
(non-tenant) query — which is likely unexpected and potentially unsafe.
This fix ensures correct tenant scoping and avoids unintended data
exposure or cache pollution.

Related issue
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9001

---------

Co-authored-by: Zakhar Bessarab <me@zekker.dev>
Co-authored-by: Max Kotliar <kotlyar.maksim@gmail.com>
2025-06-06 15:56:36 +04:00
Aliaksandr Valialkin
539498058e lib/atomicutil: add CacheLineSize const equal to the size of CPU cache line, and use this const for padding against false sharing across the code base
This should reduce the waste of memory on the padding from 128 bytes to 64 bytes on GOARCH=amd64,
while preserving bigger padding for platforms with bigger cache line sizes.

See https://stackoverflow.com/questions/68320687/why-are-most-cache-line-sizes-designed-to-be-64-byte-instead-of-32-128byte-now

Thanks to @tIGO for the hint
2025-06-06 10:21:40 +02:00
Peter Gervai
b3d22403eb docs: update LogsQL "field pipe" typo (#9037)
### Describe Your Changes

Typo? It's called "fields" pipe, not "field".

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-06-06 09:55:06 +02:00
hagen1778
0fce51e3b4 docs: prettify the changelog
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-06 09:52:02 +02:00
hagen1778
9e118fe1ee docs: rm 11831-victoria-metrics-cluster-ig1-version dashboard
Remove the community-provided dashboard as it remains without updates
for a few years already. Recommending it may hurt user's experience.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-06 09:44:37 +02:00
Zakhar Bessarab
3553c60399 app/vmctl: enable dual-stack mode by default (#9119)
Dual stack mode is disabled by default in order to avoid accidentally
exposing components via IPv6 networks.

vmctl does not expose any endpoints and does not allow using default Go
flags as it is using `urfave/cli` lib.

This commit enables IPv6 support by default since there is no security
risks related to network configuration and this make vmctl easier to use
with default configuration.

See: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9116

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-06 09:40:26 +02:00
Dmitry Ponomaryov
9b54bd6e8d app/vlinsert: add logging of skipped bytes for log lines exceeding insert.maxLineSizeBytes (#9082)
### Describe Your Changes

This change adds logging of the number of skipped bytes when a log line
exceeds the configured `insert.maxLineSizeBytes`.

it helps diagnose and tune systems dealing with oversized log records by
showing how much to increase the parameter for the log to fit in
storage.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: Dmitry Ponomaryov <iamhalje@gmail.com>
Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
2025-06-06 09:08:57 +02:00
Artur Minchukou
a90edc71c7 app/vmui/logs: optimize live tailing performance by limiting logs to 200 and notifying users (#9083)
### Describe Your Changes

Added a log limit if the 200 logs per second limit is reached and a
notification for the user asking them to add a filter to the query

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-06 09:02:43 +02:00
Nils K
83deddc84c Fix typo of journald in CLI flag (#9112)
### Describe Your Changes

Fix swapped letters

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

Signed-off-by: Septatrix <24257556+septatrix@users.noreply.github.com>
2025-06-06 08:59:16 +02:00
Jose Gómez-Sellés
434cb7028c docs/cloud: add explore data page (#9113)
### Describe Your Changes

This PR adds the explore section to the docs. It emphasizes on
explaining and linking assets for VMUI and
MetricsQL

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-06 08:53:59 +02:00
Zakhar Bessarab
107b6517b7 lib/netutil/netutil: fix strings index check
### Describe Your Changes

Properly check precense of `/`, previously it was 
ignoring a case where "/" would be at the beginning of the string.

This is a follow-up for 00712b18

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-06 09:01:50 +04:00
Fred Navruzov
f68f5b3113 docs/vmanomaly - missing updates for v1.23.0 (#9114)
### Describe Your Changes

Some of the missing doc updates after 1.23.0 release

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-05 20:21:52 +02:00
Aliaksandr Valialkin
d49b4a7550 docs/victorialogs/cluster.md: added missing -storageNode option in the example on how to disable /insert/* requests at vlselect
This is a follow-up for 41558066db

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9061
2025-06-05 18:44:17 +02:00
Aliaksandr Valialkin
bd8b4eb78b app/vmauth: add tests for the case when url_prefix ends with / and the requested path starts with /
This is needed for verifying https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9096
2025-06-05 18:37:53 +02:00
Phuong Le
41558066db vlselect/vlinsert: allow disabling the vlinsert and vlselect endpoints (#9067)
## Problem

In vlcluster evel setups, components like vlselect can still accept and
forward /insert requests. The lack of strict endpoint control increases
the risk of human error and undermines deployment security boundaries.

See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9061

## Fix

Add flags to disable the vlinsert and vlselect endpoints. The
`-insert.disable` flag also disables the internalinsert endpoint.
Similarly for vlselect.

---------

Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
2025-06-05 18:21:29 +02:00
Fred Navruzov
af064ca65a docs/vmanomaly - release v1.23.0 (#9111)
### Describe Your Changes

Docs update for vmanomaly v1.23.0 release

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-05 17:43:58 +02:00
Nikolay
eced71a96d lib/storage: properly load metric_usage_tracker file content
Previously, if metric_usage_tracker file was corrupted. It prevented
VictoriaMetrics from start and required manual action. Corruption may
happen in various reasons, such as unclean shutdown of the process.

 This commit changes panic into error message, in the same way as other
caches do.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9074
2025-06-05 14:07:31 +02:00
Aliaksandr Valialkin
23fd269ccf lib/{storage,mergeset}: reduce the multi-CPU contention on global stats vars, which are updated during background merge
Background merge updates the global stats on the number of merged / deleted items. This may result in slowdown
when multiple goroutines update these global stats at frequent rate, since every goroutine must fetch the actual value
for the updated stats from slow memory on every update. It is much faster to count the needed stats locally per every goroutine
and then periodically updating the global stats (once per ~second).

Thanks to @tIGO for the intial implementation of this idea at https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8683/files#diff-95e28ae911944708f94f3bb31fa9ba8bc185dedc23ae6fb02a272c34b8f83244

This should help improving scalability of background merges on multi-CPU systems.
See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8682
2025-06-05 12:24:03 +02:00
Aliaksandr Valialkin
1f5d02e059 lib: make sure that frequently updated global counters are padded in order to protect from false sharing issues on multi-CPU systems
Go linker packs global variables close to each other in the memory. This may lead to false sharing (https://en.wikipedia.org/wiki/False_sharing)
among these variables if frequently updated vars are put close to mostly read-only vars like described
at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8682 .

This commit adds padding to frequently updated global vars. This guarantees that these variables are put into distinct CPU cache lines
comparing to the rest of global variables. See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8683#issuecomment-2943254119

Thanks to @tIGO for the intial attempt to fix the issue at https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8683
2025-06-05 11:40:20 +02:00
Zakhar Bessarab
690aaf7d2d app/vmselect/netstorage/tenant_cache: fix inconsistent fetching of tenants list
Previously, any case when cache returned items was skipping lookup of
tenants at vmstorage nodes. This leaded to inconsistent results for
cases when cache contained items to cover only some part of requested
time range.

Fix this by forcing a cache item to cover full requested time range.
This forces cache hits to always be "full hits".

See: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9042

Target branch for this PR is another PR related to the same issue -
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9048, this is in
order to avoid additional rebasing/merge as this PR will conflict with
cluster branch after initial PR merge. GH will change target for this pr
to cluster brance once #9048 will be merged.

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-05 11:09:32 +04:00
f41gh7
1e0f7f0d28 app/vmgateway: add support of mTLS for read and write backends
This commit introduces new flags for mTLS configuration:

```
  -read.tlsCAFile
  -read.tlsCertFile
  -read.tlsInsecureSkipVerify
  -read.tlsKeyFile
  -read.tlsServerName

  -write.tlsCAFile
  -write.tlsCertFile
  -write.tlsInsecureSkipVerify
  -write.tlsKeyFile
  -write.tlsServerName
```

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8841
2025-06-04 19:36:39 +02:00
Andrii Chubatiuk
c7a16e1df6 app/vmgateway: added more select routes
This commits adds additional vmselect routes.
Such as `/static`, `/api/v1/status/metric_names_stats` and others.

 In addition it properly redirects `/vmui` and `/vmalert` access endpoints requests. Such endpoints require to preserve trailing `/`. Previously it was omitted and redirect requests failed.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9003
2025-06-04 19:36:28 +02:00
Dmytro Kozlov
2cb909022f apptest/vmctl: migrate vmctl test for the prometheus migration process (#9047)
Moved Prometheus migration process test to the apptest folder, where all
integration tests are held

Related issue https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7700

Other tests will be migrated one by one.
2025-06-04 16:40:26 +02:00
Zakhar Bessarab
fe70b963e4 app/vmselect/netstorage: allow disabling cache for list of tenants
Properly respect passing `nocache=1` or using `search.disableCache` when
executing a query. Also allow disabling tenant cache separately in order
to make debugging easier.

Related: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9042

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-04 17:05:39 +04:00
Zakhar Bessarab
9bb726751c deployment/docker: do not update stable tag
### Describe Your Changes

Stop updating `:stable` tags as those are exactly the same as `:latest`
but not used by default by docker/podman and other commands.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-04 16:57:40 +04:00
Hui Wang
3c85ffb1e6 docs: minor fixes (#9090) 2025-06-04 10:04:40 +02:00
hagen1778
65cb6468ac docs: typo fix
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-04 10:03:27 +02:00
Robin Hayer
8e645ea708 lib/workingsetcache: log error when restoring cache from file (#8952)
### What this PR does

log error returned by `fastcache.LoadFromFile` before falling back to
creating a new cache instance. this improves observability and helps
detect problems like file corruption or permission issues early.

this replaces `fastcache.LoadFromFileOrNew` with a custom function
`loadFromFileOrNewWithLog` that explicitly logs errors encountered
during cache restoration.

---

### Related Issue

Closes #8934

---

### Test Plan

- manually tested by simulating a missing file scenario  
- ensured expected log output on cache load failure  
- verified normal cache creation fallback path  

---

### Changelog

log error when cache fails to restore from file during workingsetcache
initialization (#8934)

---

### Checklist

- [x] Signed commits  
- [x] Follows coding and commit message conventions  
- [x] Tested manually  
- [x] Scope limited to relevant change  
- [x] Changelog entry added

Co-authored-by: Robin Hayer <rshayer95@gmail.com>
Co-authored-by: Roman Khavronenko <hagen1778@gmail.com>
2025-06-04 09:56:24 +02:00
Vadim Alekseev
b95bdb5781 app/vlselect: set missing Authorization header (#9089)
### Describe Your Changes

Set missing `Authorization` header when querying a storage node and
Basic Auth is enabled.

See: #9080 

### Checklist

The following checks are **mandatory**:

- [X] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
2025-06-04 08:57:06 +02:00
Aliaksandr Valialkin
5ecc5770c2 deployment/docker/Makefile: properly publish multi-architecture Docker images at latest and stable tags
The previous approach was assigning only the current architecture image to the `latest` and `stable` tags.

This is a follow-up for 02c03793b3

Thanks to @zekker6 for the initial attempt to address this issue at https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9088 .
This attempt was using a third-party component - skopeo , which must be installed manually.
This complicates the usage of the `make publish-latest` command.

The new approach, which is implemented in this commit, is to use the standard `docker buildx imagetool create` command
for creating `latest` and `stable` tags, which contain images for all the architectures from the source tag.
See https://docs.docker.com/reference/cli/docker/buildx/imagetools/create/

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7336
2025-06-04 08:46:17 +02:00
Aliaksandr Valialkin
02c03793b3 Makefile: add TAG=v1.x.y make publish-latest command for publishing latest and stable Docker image tags from the given TAG
Add the step for running this command after publishing Docker images during the release process.
See docs/victoriametrics/Release-Guide.md

This commit resolves the issue with the missing `latest` and `stable` tags after the https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7336
This also resolve issues with accidental publishing of incorrect Docker images under the `latest` and `stable` tags.
It is very easy to fix incorrectly published `latest` and `stable` tags by re-running the `TAG=v1.x.y make publish-latest` command,
which updates the `latest` and `stable` tags, so they point to the given TAG=v1.x.y.
2025-06-03 18:02:07 +02:00
hagen1778
c74c4b24d7 docs: fix broken image in victoriametrics-cloud docs
bug was introduced in 07be0c6129

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-03 16:07:37 +02:00
hagen1778
07be0c6129 docs: fix broken links in victoriametrics-cloud docs
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-03 11:56:27 +02:00
hagen1778
826c408e0e docs: fix broken links in victorialogs docs
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-03 11:52:15 +02:00
hagen1778
913b64d9b5 docs: fix broken links in victoriametrics docs
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-03 11:49:51 +02:00
hagen1778
6b76dead5a docs: fix broken links in vmanomaly docs
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-03 11:44:10 +02:00
hagen1778
41991edb34 docs: follow the same approach for assets linking as in other docs
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-03 11:37:58 +02:00
hagen1778
eb7c21bde5 docs: fix typos and reference errors in k8s monitoring guide
See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9069

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-06-03 11:32:35 +02:00
Roman Khavronenko
3cc8013dd9 docs: add guideline for merging PRs (#9066)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: Max Kotliar <kotlyar.maksim@gmail.com>
2025-06-03 11:12:22 +02:00
Hui Wang
1209f33c6d doc: clarify ingested metric usage more (#9075)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-06-03 11:05:57 +02:00
maegpankey
3c87e361ba docs: fix various typos and grammar in FAQ #9072 (#9073)
### Describe Your Changes

Fixed grammatical and phrasing issues in first half of FAQ docs.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Co-authored-by: Roman Khavronenko <hagen1778@gmail.com>
2025-06-03 11:05:19 +02:00
Aliaksandr Valialkin
f5c9c5bf01 lib/logstorage: allow using prefix filters on log fields in some LogsQL pipes
This should simplify working with big number of log fields in LogsQL queries.
Examples:

- `... | keep foo*` leaves only fields starting with `foo` prefix
- `... | rm foo*` removes all the fields starting with `foo` prefix
- `... | mv foo* bar*` replaces `foo` prefix with `bar` prefix in log fields
- `... | sum(foo*)` sums all the log fields starting with `foo` prefix
2025-06-02 22:41:57 +02:00
Aliaksandr Valialkin
7712a34ba6 docs/victorialogs/CHANGELOG.md: typo fix - use the proper link to v1.18.0-victorialogs release 2025-06-02 21:47:04 +02:00
Aliaksandr Valialkin
d890bf52fe docs/victorialogs/CHANGELOG.md: add missing closing brace 2025-06-02 21:45:08 +02:00
Aliaksandr Valialkin
f52478dac7 deployment: update VictoriaLogs Docker image tag from v1.23.2-victorialogs to v1.23.3-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.23.3-victorialogs
2025-06-02 21:43:53 +02:00
Aliaksandr Valialkin
bcc2c85e53 docs/victorialogs/CHANGELOG.md: cut the release v1.23.3-victorialogs 2025-06-02 21:38:15 +02:00
Aliaksandr Valialkin
001f9218b1 app/vlselect: properly sort results for /select/logsql/query with limit query arg and for /select/logsql/tail
The DataBlock.GetTimestamps() was returning a slice of strings, which belong to the DataBlock.
These strings are changed whenever the DataBlock is re-used for the next block.
So these strings couldn't be assigned to logRow.timestamp and to tailProcessor.lastTimestamps,
which outlive the DataBlock. The commit aa8c18fc9f5d44091d7ca92be6935eeaf3b85d7f broke this assumption,
which triggered the following bugs:

1. The bug, which could return incorrectly sorted results from /select/logsql/query when the 'limit' query arg is passed to it.
   The endpoint must return the last 'limit' log entries on the selected time range in this case, and these log entries
   must be sorted by _time.

2. The bug, which could return incorrect results from /select/logsql/tail (e.g. it could incorrectly skip some matching logs,
   it could return the same logs multiple times and it could return out-of-order logs without proper sorting by _time).

The solution is to return parsed timestamps from the DataBlock.GetTimestamps() function, so they could be safely
used by the caller without worries that they could be changed while in use.
2025-06-02 21:34:02 +02:00
Aliaksandr Valialkin
f7fc897f85 docs/victorialogs: add a link to the post from the user who migrated from 27-node Elasticsearch to a single-node VictoriaMetrics
The link is https://aus.social/@phs/114583927679254536
2025-06-02 19:18:15 +02:00
Aliaksandr Valialkin
e58b512305 docs/victorialogs/data-ingestion/DataDogAgent.md: add commonly used alias in the Internet for this page - https://docs.victoriametrics.com/victorialogs/data-ingestion/datadog/
The https://docs.victoriametrics.com/victorialogs/data-ingestion/datadog/ shows in Google Analytics report for 404 pages.
2025-06-02 18:19:06 +02:00
Aliaksandr Valialkin
d33efbbd95 app/vlselect: drop all the pipes from LogsQL query passed to HTTP querying APIs used in auto-suggestion
Auto-suggestion expects field names and values from the real logs stored in the database.
It doesn't expect field names and values created by pipes.

See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9068#issuecomment-2931275012
2025-06-02 17:53:23 +02:00
Zhu Jiekun
23cb0475e9 vmselect: remove tenant info when exporting data in native format
Fix https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9016.

Data will carry `vm_account_id` and `vm_project_id` labels when
exporting with native export API in cluster.

These labels could be treated as normal labels and be imported to
victoriametrics cluster, hence inconsistent with the source metrics
data.

e.g.:
1. source data: `{__name__="metrics_test"}`.
2. exported data: `{__name__="metrics_test", vm_account_id="0",
vm_project_id="0"}`.
3. re-imported data: `{__name__="metrics_test", vm_account_id="0",
vm_project_id="0", vm_account_id="0", vm_project_id="0"}`.
4. query result for MetricsQL `metrics_test{}`:
`{__name__="metrics_test", vm_account_id="0", vm_project_id="0"}`.
5. expect query result: `{__name__="metrics_test"}`

In VictoriaMetrics cluster, `vm_account_id` and `vm_project_id` label
are only useful when doing multi-tenant export/import. So they should be
remove if the export URL is not for multi-tenant.

This pull request:
- properly remove tenant info when exporting data in native format.

Note:
- Commit 67514c37ef23c22b91638e80e30504be23fa8dc1 is for apptest and
need to be cherry pick to master branch cc @rtm0 .

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
Co-authored-by: Roman Khavronenko <roman@victoriametrics.com>
Co-authored-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-02 19:17:44 +04:00
Nick Yang
3d3fcf8fcb docs/contribution: fix makefile target typo
### Describe Your Changes

`tests-full` (plural) target doesn't exist, but test (singular) does

discovered while working through unrelated PR

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-06-02 19:00:18 +04:00
Zakhar Bessarab
d99e3e52f3 lib/backup: add support of object metadata configuration
Add an option to configure metadata of objects when uploading backups.
For AWS S3 also support using object tagging.

Using metadata of objects is useful in order to get extended reports
about bucket content and billing details. It is also useful when
performing queries to bucket content based on metadata.

See: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8010

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
Co-authored-by: Roman Khavronenko <roman@victoriametrics.com>
2025-06-02 18:52:05 +04:00
Aliaksandr Valialkin
bbcfc0ce59 vendor: run make vendor-update 2025-06-02 16:10:26 +02:00
Aliaksandr Valialkin
d9ac6867cb vendor: update github.com/valyala/gozstd from v1.21.2 to v1.22.0
This updates upstream zstd from v1.5.6 to v1.5.7 . See https://github.com/facebook/zstd/releases/tag/v1.5.7
2025-06-02 15:52:54 +02:00
Zakhar Bessarab
00712b184b app/netstorage: improve validation for address provided at storageNode
Previously, address was always parsed as "host:port" and added port if
it was missing. This leaded to hard to understand errors in case address
was provided in "http://host:port" format.

Improve error validation in order to provide more precise error message
in case of invalid address format.

See: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9029

Previous error message: `cannot dial storageNode
"http://localhost:8488": dial tcp4: address http://localhost:8488: too
many colons in address` and vminsert continue running.
Current error message: `cannot normalize
-storageNode="http://localhost:8480": invalid address
"http://localhost:8480"; expected format: host:port` and vminsert exists
with error status code.

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-02 13:29:15 +04:00
Zakhar Bessarab
30ca617960 lib/promrelabel: follow up for aef59d9
Sync quick-template to add missing comma for the resulting JSON.

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-06-02 11:22:01 +04:00
f41gh7
aba5205896 lib/storage: properly apply retentionFilter changes
Previously, if the value of rentetionFilter was changed within the same
retention, storage didn't start background merge for historical data.

 This commits changes this behaviour by writing applied
filters into metadata.json. For backward-compatibility it reads content
of appliedRetention.txt file. It should prevent from triggering
background merge on storage update. If needed, manually remove appliedRetention.txt file from
storage/data/PART folder and remove storage.

 Also, it properly applies retentionFilter for data back-filling.
Previously, it was ignored and data outside of retention could be
ingested.

 In addition, it changes scheduling of historical merges.
Instead 2 separate background processes, storage launches a single
thread. It reduces CPU resource and disk IO resources usage.

Related issues:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8885
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4592
2025-05-30 19:38:05 +02:00
Zakhar Bessarab
aef59d9281 lib/promrelabel: prevent panic caused by invalid label name or value in debug interface
### Describe Your Changes

Previously, invalid label name or value could cause a panic of vmselect
or vmsingle as it was using MustNewLabelsFromString which was added for
usage in tests only.

Fix this by properly handling and propagating error to user interface if
there is any.

See: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8661

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-05-30 19:22:48 +02:00
Zakhar Bessarab
b1582b3012 app/vmbackupmanager: verify backup availability when creating a restore mark
Previously, restore mark could be create to a backup which does not exist or incomplete. This would lead to a crash when attempting to perform restore later on.

This commit adds verification of backup availability and completion to prevent such issues from happening. It also adds a verification bypass mechanism for cases when user wants to create a restore mark which is not currently available.

related issues:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5361
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8771
2025-05-30 15:20:44 +02:00
f41gh7
dd769d87c0 app/vmbackupmanager: add support for user-defined timezone for backup scheduling
This is useful in order to create backups at midnight in timezone specific to the user allowing to make sure backups are taken at off-peak hours of operations.

See these issues for details:
- https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6707
- https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3950

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-05-30 15:20:32 +02:00
Zhu Jiekun
febe9a2882 vmselect: dynamic concurrent dial limit
- dynamically adjusts the concurrent dial limit between 8 and 64 based
on the `-search.maxConcurrentRequests`.
- goroutines now have the chance to access available connections while
awaiting the dial limit token.

Related PR:
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8922
2025-05-30 15:14:07 +02:00
Aliaksandr Valialkin
337ccd7c62 deployment: update VictoriaLogs Docker image tag from v1.23.1-victorialogs to v1.23.2-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.23.2-victorialogs
2025-05-30 00:25:23 +02:00
Aliaksandr Valialkin
c9789b3c18 docs/victorialogs/CHANGELOG.md: cut v1.23.2-victorialogs release 2025-05-30 00:21:40 +02:00
Aliaksandr Valialkin
c9db487613 app/vlselect/vmui: run make vmui-logs-update after the commit 51fdd885ea 2025-05-30 00:20:23 +02:00
Aliaksandr Valialkin
77fffb4dc7 deployment: update VictoriaLogs Docker image tag from v1.23.0-victorialogs to v1.23.1-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.23.1-victorialogs
2025-05-30 00:05:26 +02:00
Aliaksandr Valialkin
8701ec0968 docs/victorialogs/CHANGELOG.md: cut v1.23.1-victorialogs release 2025-05-29 23:58:00 +02:00
Aliaksandr Valialkin
94f3302aca lib/logstorage: properly handle stats pipe in multi-level cluster setup when a vlselect queries another vlselect, which, in turn, queries vlstorage or another vlselect
The intermediate `vlselect` should properly proxy the `stats` state from the lower-level nodes to the upper-level `vlselect`.
Previously it was finalizing the state instead of proxying it to the upper-level `vlselect, so the upper-level `vlselect`
couldn't read it.

Fix this by introducing `proxy` mode for `stats` pipe. This mode accepts state from lower-level node, aggregates the state
and then proxies it to the upper node.

Thanks to @AndrewChubatiuk for the initial attempt to fix this issue at https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9023 .
Thanks to @func25 for the idea with introduction of a new `proxy` mode for `stats` pipe at https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9023/files#r2107735835 ,
which has been implemented in this commit. This approach results in less code changes comparing to the approach
taken at https://github.com/VictoriaMetrics/VictoriaMetrics/pull/9023

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8815
2025-05-29 20:59:05 +02:00
f41gh7
16909a2b6b lib/storage/downsampling: revert pre-filtering optimisation for downsampling rules
Skipping downsampling rules with filters based on the timestamp and offset leads to unexpected behaviour in case both rules with and without filters are present.

For example, with the following configuration: `-downsampling.period='{__name__="foo"}:60d:2m,7d:4m'`
The user would expect `foo` metrics to be downsampled only after 60d to 2m intervals. But actually pre-filter would skip scoped rule and use global rule after 7d with 4m interval.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8969
2025-05-29 19:13:14 +02:00
Yury Molodov
51fdd885ea vmui/logs: fix query trigger when chart is hidden (#9006)
### Describe Your Changes

Fix an issue where queries were not triggered when relative time was
selected and the chart was hidden.
Related issue: #8983 

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-29 15:43:50 +02:00
Yury Molodov
a213f5a423 vmui/logs: add sort pipe handling (#9004)
### Describe Your Changes

* UI now respects the `sort by` pipe in queries — if it's present, the
order returned by the server is preserved. Related issue: #8660.
* If no `sort by` pipe is used, logs are reversed on the client to show
the newest entries first (since VictoriaLogs returns them in ascending
time order — [see this in the
code](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/app/vlselect/logsql/logsql.go#L1047)).
* Removed redundant client-side time-based sorting logic.

Additionally:

* Log record fields are now sorted alphabetically in UI selectors such
as **Group by field**, **Display fields**, and **Customize columns**.
Related issue: #8438.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-29 15:41:02 +02:00
Roman Khavronenko
3a812a8b28 apptest: run tests in parallel to imrpove testing speed (#9050)
This change reduces integration tests time from 90s to 30s:
1. before
https://github.com/VictoriaMetrics/VictoriaMetrics/actions/runs/15321154610/job/43105211053?pr=9048#step:5:2
2. after
https://github.com/VictoriaMetrics/VictoriaMetrics/actions/runs/15324035886/job/43114340500#step:5:2

Signed-off-by: hagen1778 <roman@victoriametrics.com>
(cherry picked from commit 70f8c60c96)
2025-05-29 15:38:35 +02:00
hagen1778
4375699013 docs: move change 53a6bbfdf8
Move change 53a6bbfdf8 to the actual
release. Before, it was mistakenly merged to prev release.

Re-classify change from BUGFIX to FEATURE due to following reasons:
* the risk of facing this issue is low, as it reveals itself only for short staleness intervals
* it slightly changes increase_pure logic in a good way. But it is still a change, not bugfix.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-29 11:40:26 +02:00
Roman Khavronenko
53a6bbfdf8 app/vmselect/promql: detect staleness between real timestamps for increase, increase_pure or delta (#9000)
This change has effect only if one of the flags below are set:
`-search.maxLookback`, `-search.setLookbackToStep` or
`-search.maxStalenessInterval`

These flags instruct query engine to ignore data points outside of the
look-behind window if these data points are beyond the staleness
interval.

This logic is used for `removeCounterResets` function, and in functions
`increase`, `increase_pure` or `delta`. The bug described in
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8935 hit the
corner case when `removeCounterResets` detected the stale series and
`increase` did not.

The reason why staleness detection failed for `increase` is that
`removeCounterResets` calculates interval between real data points. And
`realPrevValue` (that is used by those functions) calculates the
difference between look-behind window start and previous data point.
Which, at smaller gaps or smaller staleness intervals, could affect
staleness detection and make it different to `removeCounterResets`.

This change makes `realPrevValue` to acocunt for staleness between first
data point in captured look-behind window and previous data point.

-------

While there, also updated `increase_pure` logic. It was changed in
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/1381 without
good explanation. Turns out, that `increase_pure` always compared last
value on the interval with value before the interval. While other
increase or delta functions did compare it with first data point on
interval, and only if it is missing - with the realPrevValue.

This change makes `increase_pure` logic consistent with other similar
function. The reason why it is not a separate PR is because tests
started to fail once `realPrevValue` callculation logic changed and
there were no good solution to isolate this change.

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: Max Kotliar <kotlyar.maksim@gmail.com>
2025-05-29 11:23:46 +02:00
Hui Wang
897f1b97e3 docs: fix cmd-line flag default values in description (#9008)
follow up
b9f080321c
2025-05-29 11:19:13 +02:00
Hui Wang
309f1898b3 alerts: fix the alerting rule ScrapePoolHasNoTargets (#9045)
as it may cause false positive in [sharding
mode](https://docs.victoriametrics.com/victoriametrics/vmagent/#scraping-big-number-of-targets)

related https://github.com/VictoriaMetrics/helm-charts/issues/2200
2025-05-29 11:17:52 +02:00
Alexander Marshalov
8998526384 docs/vmcloud: add info about api go client to the docs (#9040)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-29 00:32:23 +02:00
Aliaksandr Valialkin
e55e2a4274 docs/victoriametrics/Cluster-VictoriaMetrics.md: update description for the -downsampling.period command-line flag after the commit 7dbfe1e5474b69cd1ab7cc8b5e936b6dc62d5f71 2025-05-29 00:13:45 +02:00
Aliaksandr Valialkin
29ec5d2898 all: consistently end docs.victoriametrics.com urls with /
Urls to docs.victoriametrics.com, which do not end with `/`, are working, but they lead to an unnecessary redirect to /index.html url,
which breaks backwards navigation. For example, https://docs.victoriametrics.com/victoriametrics/integrations/prometheus
redirects to https://docs.victoriametrics.com/victoriametrics/integrations/prometheus/index.html .

So it is better to consistently end all the urls to docs.victoriametrics.com with `/` in order to prevent
the unnecessary redirect and preserve backwards navigation. E.g. https://docs.victoriametrics.com/victoriametrics/integrations/prometheus
is replaced with https://docs.victoriametrics.com/victoriametrics/integrations/prometheus/ , etc.

This is a follow-up for commits starting from 6ec422160b
2025-05-29 00:05:30 +02:00
Aliaksandr Valialkin
adef9693af docs/victoriametrics-cloud: consistently use absolute links to VictoriaMetrics Cloud docs after the commit cddf36af43 2025-05-29 00:05:30 +02:00
Aliaksandr Valialkin
8f01ac42a8 docs/victoriametrics/integrations/prometheus.md: add an alias /data-ingestion/prometheus/ , since it is already used all over the Internet after the commit a46d554f74
The link to https://docs.victoriametrics.com/victoriametrics/data-ingestion/prometheus/ became borken after the commit 7d199d1d83,
which renamed the link to https://docs.victoriametrics.com/victoriametrics/integrations/prometheus .
2025-05-29 00:05:29 +02:00
Vadim Alekseev
8223a5235f deployment/logs-benchmark: fix URLs to benchmark data (#9030)
### Describe Your Changes

When downloading archives for benchmarks, an error appears saying that
the archive was placed in a new path.

The error could have been prevented by providing the `-L (--location)`
flag that would tell curl to follow the redirect, so in addition to
updating the paths, this flag was added.

### Checklist

The following checks are **mandatory**:

- [X] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-28 16:39:06 +02:00
Cheyi Lin
fe5f2bd5d7 dashboards: fix newline escape in panel descriptions (#9036)
### Describe Your Changes

Fix extra newline escape characters in panel descriptions.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-28 16:37:46 +02:00
Aliaksandr Valialkin
00075ac4ee deployment: update VictoriaLogs Docker image tag from v1.22.2-victorialogs to v1.23.0-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.23.0-victorialogs
2025-05-28 14:26:55 +02:00
Aliaksandr Valialkin
3f39946f99 docs/victorialogs/CHANGELOG.md: cut v1.23.0-victorialogs release 2025-05-28 14:20:21 +02:00
Aliaksandr Valialkin
1ddfd55e51 docs/victorialogs/logsql-examples.md: add an example how to get duration since the last seen log, which matches the given filter
This is a follow-up for 5bb012b67b

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9013
2025-05-28 14:04:14 +02:00
Phuong Le
5bb012b67b logsql: math now() (#9014)
Resolves https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9013
2025-05-28 13:43:23 +02:00
Phuong Le
78fb987bef vlstorage: automatically recover missing parts.json files on startup (#9007)
Fixes
[#8873](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8873).

Automatically recover missing `parts.json` files on startup.
VictoriaLogs now scans existing part directories and recreates missing
`parts.json` files instead of crashing. This aligns with
VictoriaMetrics' approach.

---------

Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
2025-05-28 13:19:05 +02:00
Aliaksandr Valialkin
a0084dc223 docs/victorialogs/LogsQL.md: remove superflouos "returns" word 2025-05-27 15:56:41 +02:00
Phuong Le
f5ffbb4e00 logsql: Remove redundant suffix logic (#9022)
1. Add `!lex.isEnd()` to prevent an infinite loop. Although the current
code doesn't trigger this bug, it's a latent issue that could occur if
someone modifies the callers or adds new code paths without proper stop
tokens.
2025-05-27 14:00:37 +02:00
Jose Gómez-Sellés
13d2b0b558 docs/cloud: adapt integrations (#9032)
This PR improves integrations docs in 2 areas:
- Background set to white, avoiding issues when changing to dark mode.
- Height set to avoid blank spaces

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-27 10:59:47 +02:00
Evgeny
b83b2bae3b fix for multiple users running tests (testStoragePath ownership issue) (#9015)
### Describe Your Changes

When multiple users run tests on the same instance, the first user
creating a folder will own the testStoragePath, which can lead to issues
accessing this folder for other users. This change will allow us to
create unique folders per user.

```
% ls -ld /usr/tmp/vmalert-unittest/
drwxr-xr-x 2 some_user users 4096 May 12 17:22 /usr/tmp/vmalert-unittest/
...
2025-05-20T13:56:16.488Z        panic   lib/fs/fs.go:132        FATAL: cannot create directory: mkdir /usr/tmp/vmalert-unittest/1747749376488491648: permission denied
panic: FATAL: cannot create directory: mkdir /usr/tmp/vmalert-unittest/1747749376488491648: permission denied
```

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Co-authored-by: Hui Wang <haley@victoriametrics.com>
2025-05-27 15:09:56 +08:00
Artem Fetishev
ef84c16f37 Bump VictoriaMetrics version mentioned in docs
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-26 13:49:56 +02:00
Artem Fetishev
47391fea3b deployment/docker: Bump VictoriaMetrics version
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-26 13:39:08 +02:00
Artem Fetishev
afce8bc320 docs: bump last LTS versions
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-26 13:34:53 +02:00
Artem Fetishev
5d18cd3416 docs/CHANGELOG.md: update changelog with LTS release notes
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-26 13:30:19 +02:00
hagen1778
65e0b3b86f deployment/dashboards: update PendingDataPoints description
Mention that data is flushed every 5s, not 2s.
Hence, expected pending data points is x5.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-26 10:58:48 +02:00
Artem Fetishev
aa3171cf4b docs/CHANGELOG.md: cut v1.118.0
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-23 14:40:22 +02:00
Artem Fetishev
1754ac53cd make vmui-update and make vmui-logs-update
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-23 11:21:53 +02:00
hagen1778
5c6af65e48 deployment/dashboards: add panels for PSI metrics
Add panels for CPU, IO and Memory pressure to vmalert, vmagent,
VictoriaMetrics single/cluster and VictoriaLogs single/cluster dashboards.

https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8966
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-22 16:54:52 +02:00
Phuong Le
d8871f56ba lib/logstorage/parse: fix incorrect endTime in AddTimeFilter (#8991)
Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8985

When using `AddTimeFilter`, it creates a string representation with the
exact same timestamps but doesn't transform the internal end value. This
is different from the `parseFilterTime` function, which makes the
behavior of these two paths different.
2025-05-22 16:45:12 +02:00
Zakhar Bessarab
4d6bc3b5df app/vmselect/prometheus: follow-up after 60e253b
Prevent panic on instant queries when `-search.queryStats.lastQueriesCount=0` is set.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-22 15:50:02 +02:00
Zakhar Bessarab
60e253b387 app/vmselect/prometheus: prevent panic when querying with disabled query stats tracking (#8974)
Previously, querying with disabled tracking would lead to loading nil
value of execution duration. `qs.SeriesFetched` does not need similar
handling as it uses atomic.Int64 and has default value anyway.

See: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8973

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-05-22 15:38:15 +02:00
dependabot[bot]
127d6972ac build(deps): bump react-router and react-router-dom in /app/vmui/packages/vmui (#8859)
Bumps
[react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router)
to 7.5.3 and updates ancestor dependency
[react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom).
These dependencies need to be updated together.

Updates `react-router` from 7.5.0 to 7.5.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/remix-run/react-router/releases">react-router's
releases</a>.</em></p>
<blockquote>
<h2>v7.5.3</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v753">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v753</a></p>
<h2>v7.5.2</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v752">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v752</a></p>
<h2>v7.5.1</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v751">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v751</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md">react-router's
changelog</a>.</em></p>
<blockquote>
<h2>7.5.3</h2>
<h3>Patch Changes</h3>
<ul>
<li>Fix bug where bubbled action errors would result in
<code>loaderData</code> being cleared at the handling
<code>ErrorBoundary</code> route (<a
href="https://redirect.github.com/remix-run/react-router/pull/13476">#13476</a>)</li>
<li>Handle redirects from <code>clientLoader.hydrate</code> initial load
executions (<a
href="https://redirect.github.com/remix-run/react-router/pull/13477">#13477</a>)</li>
</ul>
<h2>7.5.2</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p>Update Single Fetch to also handle the 204 redirects used in
<code>?_data</code> requests in Remix v2 (<a
href="https://redirect.github.com/remix-run/react-router/pull/13364">#13364</a>)</p>
<ul>
<li>This allows applications to return a redirect on <code>.data</code>
requests from outside the scope of React Router (i.e., an
<code>express</code>/<code>hono</code> middleware)</li>
<li>⚠️ Please note that doing so relies on implementation details that
are subject to change without a SemVer major release</li>
<li>This is primarily done to ease upgrading to Single Fetch for
existing Remix v2 applications, but the recommended way to handle this
is redirecting from a route middleware</li>
</ul>
</li>
<li>
<p>Adjust approach for Prerendering/SPA Mode via headers (<a
href="https://redirect.github.com/remix-run/react-router/pull/13453">#13453</a>)</p>
</li>
</ul>
<h2>7.5.1</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p>Fix single fetch bug where no revalidation request would be made when
navigating upwards to a reused parent route (<a
href="https://redirect.github.com/remix-run/react-router/pull/13253">#13253</a>)</p>
</li>
<li>
<p>When using the object-based <code>route.lazy</code> API, the
<code>HydrateFallback</code> and <code>hydrateFallbackElement</code>
properties are now skipped when lazy loading routes after hydration. (<a
href="https://redirect.github.com/remix-run/react-router/pull/13376">#13376</a>)</p>
<p>If you move the code for these properties into a separate file, you
can use this optimization to avoid downloading unused hydration code.
For example:</p>
<pre lang="ts"><code>createBrowserRouter([
  {
    path: &quot;/show/:showId&quot;,
    lazy: {
loader: async () =&gt; (await
import(&quot;./show.loader.js&quot;)).loader,
Component: async () =&gt; (await
import(&quot;./show.component.js&quot;)).Component,
      HydrateFallback: async () =&gt;
(await import(&quot;./show.hydrate-fallback.js&quot;)).HydrateFallback,
    },
  },
]);
</code></pre>
</li>
<li>
<p>Properly revalidate prerendered paths when param values change (<a
href="https://redirect.github.com/remix-run/react-router/pull/13380">#13380</a>)</p>
</li>
<li>
<p>UNSTABLE: Add a new <code>unstable_runClientMiddleware</code>
argument to <code>dataStrategy</code> to enable middleware execution in
custom <code>dataStrategy</code> implementations (<a
href="https://redirect.github.com/remix-run/react-router/pull/13395">#13395</a>)</p>
</li>
<li>
<p>UNSTABLE: Add better error messaging when <code>getLoadContext</code>
is not updated to return a <code>Map</code>&quot; (<a
href="https://redirect.github.com/remix-run/react-router/pull/13242">#13242</a>)</p>
</li>
<li>
<p>Do not automatically add <code>null</code> to
<code>staticHandler.query()</code> <code>context.loaderData</code> if
routes do not have loaders (<a
href="https://redirect.github.com/remix-run/react-router/pull/13223">#13223</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9a41029f58"><code>9a41029</code></a>
chore: Update version for release (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/13482">#13482</a>)</li>
<li><a
href="945295b711"><code>945295b</code></a>
chore: Update version for release (pre) (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/13479">#13479</a>)</li>
<li><a
href="501d554cba"><code>501d554</code></a>
Handle redirects from hydrating clientLoaders (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/13477">#13477</a>)</li>
<li><a
href="2a128f1b91"><code>2a128f1</code></a>
Fix cleared loaderData bug on thrown action errors (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/13476">#13476</a>)</li>
<li><a
href="5819e0c45d"><code>5819e0c</code></a>
chore: Update version for release (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/13456">#13456</a>)</li>
<li><a
href="d0cac3395f"><code>d0cac33</code></a>
chore: Update version for release (pre) (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/13454">#13454</a>)</li>
<li><a
href="c84302972a"><code>c843029</code></a>
Adjust approach for prerendering/SPA mode via headers (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/13453">#13453</a>)</li>
<li><a
href="8e4963faec"><code>8e4963f</code></a>
Restore handling of 204 &quot;soft&quot; redirects on data requests (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/13364">#13364</a>)</li>
<li><a
href="ed77157ed5"><code>ed77157</code></a>
update session documentation links (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/13448">#13448</a>)</li>
<li><a
href="4281172339"><code>4281172</code></a>
Missed refactor updates</li>
<li>Additional commits viewable in <a
href="https://github.com/remix-run/react-router/commits/react-router@7.5.3/packages/react-router">compare
view</a></li>
</ul>
</details>
<br />

Updates `react-router-dom` from 7.5.0 to 7.5.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/remix-run/react-router/releases">react-router-dom's
releases</a>.</em></p>
<blockquote>
<h2>react-router-dom-v5-compat@6.4.0-pre.15</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies
<ul>
<li>react-router@6.4.0-pre.15</li>
<li>react-router-dom@6.4.0-pre.15</li>
</ul>
</li>
</ul>
<h2>react-router-dom-v5-compat@6.4.0-pre.11</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies
<ul>
<li>react-router@6.4.0-pre.11</li>
<li>react-router-dom@6.4.0-pre.11</li>
</ul>
</li>
</ul>
<h2>react-router-dom-v5-compat@6.4.0-pre.10</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies
<ul>
<li>react-router@6.4.0-pre.10</li>
<li>react-router-dom@6.4.0-pre.10</li>
</ul>
</li>
</ul>
<h2>react-router-dom-v5-compat@6.4.0-pre.9</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies
<ul>
<li>react-router@6.4.0-pre.9</li>
<li>react-router-dom@6.4.0-pre.9</li>
</ul>
</li>
</ul>
<h2>react-router-dom-v5-compat@6.4.0-pre.8</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies
<ul>
<li>react-router@6.4.0-pre.8</li>
<li>react-router-dom@6.4.0-pre.8</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md">react-router-dom's
changelog</a>.</em></p>
<blockquote>
<h2>7.5.3</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies:
<ul>
<li><code>react-router@7.5.3</code></li>
</ul>
</li>
</ul>
<h2>7.5.2</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies:
<ul>
<li><code>react-router@7.5.2</code></li>
</ul>
</li>
</ul>
<h2>7.5.1</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies:
<ul>
<li><code>react-router@7.5.1</code></li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9a41029f58"><code>9a41029</code></a>
chore: Update version for release (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom/issues/13482">#13482</a>)</li>
<li><a
href="945295b711"><code>945295b</code></a>
chore: Update version for release (pre) (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom/issues/13479">#13479</a>)</li>
<li><a
href="5819e0c45d"><code>5819e0c</code></a>
chore: Update version for release (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom/issues/13456">#13456</a>)</li>
<li><a
href="d0cac3395f"><code>d0cac33</code></a>
chore: Update version for release (pre) (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom/issues/13454">#13454</a>)</li>
<li><a
href="5dd7c1580f"><code>5dd7c15</code></a>
chore: Update version for release (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom/issues/13422">#13422</a>)</li>
<li><a
href="6ce4a79774"><code>6ce4a79</code></a>
chore: Update version for release (pre) (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom/issues/13412">#13412</a>)</li>
<li>See full diff in <a
href="https://github.com/remix-run/react-router/commits/react-router-dom@7.5.3/packages/react-router-dom">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/VictoriaMetrics/VictoriaMetrics/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-22 15:24:52 +02:00
Andrii Chubatiuk
6d7d22f3e6 deployment/docker/victorialogs: add grafana alloy setup (#8908)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-05-22 15:24:29 +02:00
Komei Kamiya
6a4757ad06 deployment: fix compose.yml for victorialogs fluentbit otlp demo (#8987)
### Describe Your Changes

compose.yml does not exist, only compose-base.yml

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-22 15:00:05 +02:00
Dima Shur
ff0632c01e docs: changed typo in histogram_bucket - metricsQL query was in wrong place (#8999)
### Describe Your Changes

MetricsQL code was in wrong place - moved it 5 lines higher

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-05-22 14:49:10 +02:00
Phuong Le
134501bf99 docs/relabeling: improve readability (#8633)
This commit re-fines the relabeling cookbok and moves all
relabeling related docs to the same page. 
It also removes duplicated information from vmagent readme.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-05-22 14:46:06 +02:00
Hui Wang
faa3943a25 deployment-docker: fix vmalert -remoteWrite.url arg (#8986)
vmalert auto adds `/api/v1/write` if `remoteWrite.disablePathAppend` is not specified
2025-05-22 10:47:12 +08:00
Artem Fetishev
b30f4ca12a Release-Guide.md: Update link to enterprise release guide and remove Public Announcement section (#8978)
The link to enterprise release guide now points to the doc in
enterprise-single-node branch instead of enterprise master. This is
because we don't use enterprise master.

Additionally the `Public Announcement` section has been removed because
we don't make public announcements for releases.

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-21 11:16:17 +02:00
Zakhar Bessarab
208515dc38 lib/promscrape/discovery/k8s: fix inconsistency with Prometheus for endpointslice discovery
Add missing labels for:
- node name
- endpoint "serving" and "terminating" states

See: https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8959

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-05-19 17:28:53 +04:00
Jose Gómez-Sellés
9de3e80a4f Docs/cloud: complete deployments section (#8928)
### Describe Your Changes

As planned, we are adding a more structured way of explaining
deployments and tiers.
In this PR the following changes are added:
- The previous tiering section is moved under the deployments
placeholder
- Explanations for users to pick single or cluster 
- Explanations for different parameters
- Re-styling of the docs to look more appealing
- Reorder some hanging docs so the sections are more clearly presented
to the users

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Co-authored-by: Alexander Marshalov <_@marshalov.org>
2025-05-19 10:15:45 +02:00
hagen1778
63d8d0c5ac docs: remove link to #filtering as it has conflicts in vmctl doc
Apparently, when the doc was created for vmctl the anchor conflicts
weren't accounted for or weren't a thing yet. Now, various migration modes
have conflicting anchors. This should be addressed in follow-up commits.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-16 21:59:26 +02:00
hagen1778
6b485c4e46 docs: revise Prometheus migration section in vmctl
Improve wording and instructions. It has been a while since the last
time we updated it (more than 4 years!).

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-16 21:47:45 +02:00
GitHub Snyk Bot
723e56ac50 [Snyk] Security upgrade vite from 6.2.6 to 6.2.7 (#8866)
![snyk-top-banner](https://res.cloudinary.com/snyk/image/upload/r-d/scm-platform/snyk-pull-requests/pr-banner-default.svg)

### Snyk has created this PR to fix 1 vulnerabilities in the npm
dependencies of this project.

#### Snyk changed the following file(s):

- `app/vmui/packages/vmui/package.json`
- `app/vmui/packages/vmui/package-lock.json`




#### Vulnerabilities that will be fixed with an upgrade:

|  | Issue | Score | 

:-------------------------:|:-------------------------|:-------------------------
![medium
severity](https://res.cloudinary.com/snyk/image/upload/w_20,h_20/v1561977819/icon/m.png
'medium severity') | Directory Traversal
<br/>[SNYK-JS-VITE-9919777](https://snyk.io/vuln/SNYK-JS-VITE-9919777) |
&nbsp;&nbsp;**693**&nbsp;&nbsp;




---

> [!IMPORTANT]
>
> - Check the changes in this PR to ensure they won't cause issues with
your project.
> - Max score is 1000. Note that the real score may have changed since
the PR was raised.
> - This PR was automatically created by Snyk using the credentials of a
real user.

---

**Note:** _You are seeing this because you or someone else with access
to this repository has authorized Snyk to open fix PRs._

For more information: <img
src="https://api.segment.io/v1/pixel/track?data=eyJ3cml0ZUtleSI6InJyWmxZcEdHY2RyTHZsb0lYd0dUcVg4WkFRTnNCOUEwIiwiYW5vbnltb3VzSWQiOiI1ZTlmZjBkYy01MjQ0LTQzMGYtYTc3MS0yMTY1MjdjN2Q1NjEiLCJldmVudCI6IlBSIHZpZXdlZCIsInByb3BlcnRpZXMiOnsicHJJZCI6IjVlOWZmMGRjLTUyNDQtNDMwZi1hNzcxLTIxNjUyN2M3ZDU2MSJ9fQ=="
width="0" height="0"/>
🧐 [View latest project
report](https://app.snyk.io/org/victoriametrics/project/69d9ccbb-b5b1-492f-9f8c-9032dcaf021e?utm_source&#x3D;github&amp;utm_medium&#x3D;referral&amp;page&#x3D;fix-pr)
📜 [Customise PR
templates](https://docs.snyk.io/scan-using-snyk/pull-requests/snyk-fix-pull-or-merge-requests/customize-pr-templates?utm_source=github&utm_content=fix-pr-template)
🛠 [Adjust project
settings](https://app.snyk.io/org/victoriametrics/project/69d9ccbb-b5b1-492f-9f8c-9032dcaf021e?utm_source&#x3D;github&amp;utm_medium&#x3D;referral&amp;page&#x3D;fix-pr/settings)
📚 [Read about Snyk's upgrade
logic](https://docs.snyk.io/scan-with-snyk/snyk-open-source/manage-vulnerabilities/upgrade-package-versions-to-fix-vulnerabilities?utm_source=github&utm_content=fix-pr-template)

---

**Learn how to fix vulnerabilities with free interactive lessons:**

🦉 [Directory
Traversal](https://learn.snyk.io/lesson/directory-traversal/?loc&#x3D;fix-pr)

[//]: #
'snyk:metadata:{"customTemplate":{"variablesUsed":[],"fieldsUsed":[]},"dependencies":[{"name":"vite","from":"6.2.6","to":"6.2.7"}],"env":"prod","issuesToFix":["SNYK-JS-VITE-9919777"],"prId":"5e9ff0dc-5244-430f-a771-216527c7d561","prPublicId":"5e9ff0dc-5244-430f-a771-216527c7d561","packageManager":"npm","priorityScoreList":[693],"projectPublicId":"69d9ccbb-b5b1-492f-9f8c-9032dcaf021e","projectUrl":"https://app.snyk.io/org/victoriametrics/project/69d9ccbb-b5b1-492f-9f8c-9032dcaf021e?utm_source=github&utm_medium=referral&page=fix-pr","prType":"fix","templateFieldSources":{"branchName":"default","commitMessage":"default","description":"default","title":"default"},"templateVariants":["updated-fix-title","priorityScore"],"type":"auto","upgrade":["SNYK-JS-VITE-9919777"],"vulns":["SNYK-JS-VITE-9919777"],"patch":[],"isBreakingChange":false,"remediationStrategy":"vuln"}'

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
2025-05-16 16:07:28 +02:00
Andrii Chubatiuk
0a4f7e0958 app/vmui: add command to run vmui with victoriametrics playground env (#8927)
### Describe Your Changes

added command to run vmui locally backed by vm playground

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-16 16:07:07 +02:00
Artur Minchukou
9eb6796bad app/vmui/logs: properly escape special characters in field values shown in autocomplete suggestions
### Describe Your Changes

Related issue: #8925 

Properly escaped special characters in field values shown in
autocomplete suggestions.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-16 16:02:20 +02:00
Artem Fetishev
1916f5be4b lib/storage: make the test pass on systems with 1 CPU (#8949)
The following test produces duplicate per-day index records on a system
with 1 CPU even when data inserted sequentially:

```
GOEXPERIMENT=synctest taskset -c 0 go test ./lib/storage -run=TestStorageAddRowsForVariousDataPatternsConcurrently/perDayIndexes/serial/sameBatchMetrics/sameRowMetrics/sameBatchDates/diffRowDates
```

See: #8654

Make this test pass by relaxing got and want data equality requirement
if the number of CPUs is 1. This is temporary until one insertion corner
case is fixed:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8948

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-16 15:54:11 +02:00
hagen1778
4207cb8450 docs: add trailing / to links
See comment 266bceaffd (r157230824)

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-16 15:46:37 +02:00
Artur Minchukou
231bfcf4cf app/vmui: add live tailing tab to Victoria Logs (#8882)
### Describe Your Changes

Related issue: #7046 

Changes:
- add JSX automatic runtime import of React, you don't need to import
React anymore in JSX files.
 - add unused imports eslint rule
- add headers to ProcessLiveTailRequest to enable client-side connection
setup
- refactor ExploreLogs: divided the component into several separate
components for better readability and code maintenance
 - add live tailing tab to VictoriaLogs

short demo:


https://github.com/user-attachments/assets/3e5f57ee-8e72-4835-9fc6-35c6f38bc9ef



### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-05-16 15:37:55 +02:00
Max Kotliar
03ceeb7211 docs: capitalize "Enterprise" in VictoriaMetrics Enterprise phrase (#8950)
### Describe Your Changes

Capitalize "Enterprise" in VictoriaMetrics Enterprise phrase

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-16 15:17:01 +02:00
Max Kotliar
118a322aa4 docs/victoriametrics/changelog: Improve relabel bug fix changelog message (#8951)
### Describe Your Changes

 Improve relabel bug fix changelog message

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-16 15:13:05 +02:00
Hui Wang
454ad7a1b4 alerts: improve disk full estimation (#8955)
enhance alerting rule `DiskRunsOutOfSpaceIn3Days` and
`NodeBecomesReadonlyIn3Days` to account for
[deduplication](https://docs.victoriametrics.com/#deduplication) and
[indexDB](https://docs.victoriametrics.com/#indexdb) when calculating
disk consumption rate.

And try bring the `Storage full ETA` panel back.

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-05-16 15:11:12 +02:00
hagen1778
266bceaffd docs: demote links used for backward compatibility
Move anchors that were kept only for backward-compatibility reasons
to the bottom of the document. So they don't take extra space in main doc.

Demote anchor level to `h6`, so docs engine will stop rendering in the
right navigation column.

In this way, we still keep the backward compatibility: old links will
continue working. And free space occupied by these link in the main doc.
Thanks to @makasim for the idea.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-16 15:06:55 +02:00
Hui Wang
60322ed491 vmalert: drop duplicate labels when they appear in both the recording… (#8957)
… rule label spec and the expression result

address https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8954

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-05-16 13:47:54 +02:00
Andrii Chubatiuk
18f4c1f646 app/vlinsert: return HTTP 202 on successfully ingested Datadog logs (#8958)
### Describe Your Changes

fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8956

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-16 13:38:46 +02:00
hagen1778
45e6491a8e docs: mention where known issues were resolved
* mention which release got the bugfix
* unify `known issues` message

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-16 13:35:35 +02:00
f41gh7
0108d5777c docs: release follow-up
* mention new app versions
* add lts releases changelog
2025-05-15 17:40:59 +02:00
Max Kotliar
4fabb459aa changelog: add advice to skip affected versions
Add a note to skip the latest releases, because of the bug in vmagent.
Fixed in https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8941
2025-05-15 17:33:49 +02:00
f41gh7
75623173d4 make linter happy after e2ddf2ba52
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-05-15 12:51:56 +02:00
f41gh7
f26f84cc4f CHANGELOG.md: cut v1.117.1 release 2025-05-15 12:30:49 +02:00
Andrii Chubatiuk
d68d0b67ca app/vmagent: fixed typo at relabel config reloading
Commit 3b84f45e0a introduce a typo at `relabelConfigs.IsSet` function. It incorrectly returned value if relabeling configuration is set or not.
As a result, vmagent was not able to properly perform relabel configuration reload.
And incorrectly exposed metrics for reload configuration.

Related issue:
https://github.com/VictoriaMetrics/helm-charts/issues/2119
2025-05-15 12:26:39 +02:00
smallpath
e2ddf2ba52 lib/promauth: properly reload config on headers changes
Previously, headers hash calculation had a typo, instead of `hash.Write` - `hash.Sum` method was used.
It discards any previous writes and as a result digest always had the same value. It prevented from proper config reload.

 This commit fixes this typo and properly calculates headers digest. 

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8931
2025-05-15 12:14:22 +02:00
Phuong Le
21c06e86db net/http: close the body
Close the body to avoid leaking goroutines
2025-05-14 11:07:54 +02:00
Andrii Chubatiuk
93eaea9754 lib/protoparser/datadogsketches: fixed duplications in datadog sketches aggregations
Previously, due to bug at parsing logic sketches values were duplicated.

This commit properly parsers sketches and correctly converts it to time series labels.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8836
2025-05-14 10:50:39 +02:00
Vadim Alekseev
d1d8be8d9b app/vlinsert: handle nested fields in the otel ingestion handle
Previously, OTL attributes fields with KeyValue type were ingested as a single json formated field. It complicates requests and requires extra effort at query time.

 This commit adds support for handling nested fields to match the behavior of
other handlers, such as `/jsonline`. KeyValue attribute will be converted into separate field.


Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8862
2025-05-14 10:46:16 +02:00
Zakhar Bessarab
b9b0b73d29 make/docker: stop updating :latest and :stable tags
Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7336
2025-05-14 10:43:07 +02:00
Hui Wang
6dfd7fb518 docs: minor fix
https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/#how-to-delete-time-series
doesn't exist.
2025-05-14 10:42:11 +02:00
Artem Fetishev
fde196c86e docs/Release-Guide.md: Fix formatting and outdated instructions (#8932)
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-13 13:47:35 +02:00
hagen1778
6c08fae64f docs: mention how to set alert source example in docker
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-12 22:59:47 +02:00
Hui Wang
cdaf83247c docker-deployment: update vmalert external.alert.source flag (#8926)
follow up
4de8113f39
2025-05-12 22:58:45 +02:00
Artem Fetishev
c1911a00de docs: Bump VictoriaMetrics version mentioned in docs
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-12 14:40:10 +02:00
Artem Fetishev
56e3568492 deployment: Bump VictoriaMetrics version at deployment/docker/*.yml
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-12 14:28:12 +02:00
Artem Fetishev
19d3c44391 docs: bump last LTS versions
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-12 12:34:38 +02:00
Artem Fetishev
ab15ffcf3a docs/CHANGELOG.md: update changelog with LTS release notes
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-12 12:30:29 +02:00
Artur Minchukou
82a4889adb app/vmui: add command to run VictoriaLogs with playground env (#8910)
### Describe Your Changes

Added npm command `npm run start:logs:playground` to run VictoriaLogs UI
with playground env.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-12 09:02:43 +02:00
Zakhar Bessarab
f1502b7d16 vendor: remove pin for prometheus/prometheus (#8905)
### Describe Your Changes
Version with the latest changes from prometheus/common have been
released as v0.303.1 so builds are no longer failing.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-05-12 09:01:35 +02:00
hagen1778
1dd8327821 docs: add alias victorialogs/LogsQL which lead to 404 before
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-12 08:59:33 +02:00
hagen1778
b0bf7fd7d5 docs: add unique identifier to ReleaseGuide page
It solves the following build error:
```
duplicate menu entry with identifier "Release process guidance" in menu "docs"
```

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-12 08:57:38 +02:00
hagen1778
e3b907bccc docs: fix typo in links to FIPS builds
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-12 08:56:41 +02:00
Aliaksandr Valialkin
632bab85cf lib/logstorage: move fieldsFilter to lib/prefixfilter in the preparation for its use instead of fieldsSet
While at it, make sure that _msg field name is uniformly treated as an empty field name ("") during data ingestion.
2025-05-12 08:34:07 +02:00
Fred Navruzov
03d3fad3b7 docs/vmanomaly: release v1.22.1 (#8919)
### Describe Your Changes

Update /anomaly-detection/ docs according to release `v1.22.1`
P.s. The links in guides and quickstarts were not intentionally set to
v1.22.1 until we fully restore parallelization in forthcoming releases
and mark it as a go-to release everywhere

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-11 22:16:50 +02:00
Aliaksandr Valialkin
b2bf237466 lib/logstorage: simplify blockResultColumn.getValuesEncoded() a bit by removing columnValuesEncodedCreator and searchValuesEncodedCreator abstractions
There are three possible cases for blockResultColumn.getValuesEncoded():

- The blockResultColumn.valuesEncoded is already set. This is the case for manually constructed blockResultColumn,
  or if it is cloned via blockResult.clone().

- The blockResultColumn.chSrc is non-nil. In this case the valuesEncoded must be read from the corresponding br.bs,
  by applying br.bm filter.

- The blockResultColumn.cSrc is non-nil. In this case the valuesEncoded must be read from the corresponding br.brSrc,
  by applying br.bm filter.

It is better from maintainability and debuggability PoV to write this logic in a single getValuesEncoded() function
instead of indirecting it via valuesEncodedCreator.
2025-05-10 13:12:54 +02:00
Aliaksandr Valialkin
3f379ee5fd lib/logstorage: avoid reading timestamps when processing "filter" pipe and "if()" conditions at "stats" pipe
This should speed up such queries a bit if the timestamps isn't used in such a queries.
2025-05-10 12:37:47 +02:00
Aliaksandr Valialkin
6399372d6f deployment: update VictoriaLogs Docker image tag from v1.22.1-victorialogs to v1.22.2-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.22.2-victorialogs
2025-05-10 03:19:30 +02:00
Aliaksandr Valialkin
90fc5d155c docs/victorialogs/CHANGELOG.md: cut v1.22.2-victorialogs release 2025-05-10 03:12:30 +02:00
Aliaksandr Valialkin
208c3fe061 lib/logstorage: fix improper calculation of min / max over numeric columns
VictoriaLogs stores min and max column values per every data block.
These values were incorrectly used by min() and max() stats functions
inside updateStatsForAllRows() function. It was assumed that this function
could use min / max values stored in the block, since all the rows in the blockResult
must be processed. But the blockResult contains _filtered_ rows,
e.g. it may have less rows than the number of rows in the original block.
In this case it is unsafe assuming that the min / max values from the original block
exist in the filtered rows inside blockResult.

Add blockResult.isFull() function, which returns true if the blockResult contains all rows
from the original block (e.g. they aren't filtered). Use this function in fast path,
while fall back to slow path, which triggers reading the column values and iterating over them.
2025-05-10 03:05:33 +02:00
Aliaksandr Valialkin
236f678d09 docs/victorialogs/_index.md: added /VictoriaLogs.html alias, since it is used in the Internet according to Google Analytics (this page leads "404 Not Found" error 2025-05-10 01:59:25 +02:00
Aliaksandr Valialkin
378cb83f67 lib/logstorage: treat '_msg' and '' as the same field names inside filedsFilter
The '_msg' and '' field names are interchangeable, so they must be treated the same in filters.
2025-05-09 23:23:35 +02:00
Artem Fetishev
e82240d507 docs/CHANGELOG.md: cut v1.117.0
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-09 16:33:03 +02:00
Artem Fetishev
5ff4551b47 make docs-update-version
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-09 16:25:07 +02:00
Artem Fetishev
513c88fca5 app/{vmselect,vlselect}: run make vmui-update vmui-logs-update
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-09 15:51:52 +02:00
Alexander Marshalov
3d03daac8a vmcloud: small fixes in access tokens docs (#8915)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [X] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-09 10:20:34 +02:00
hagen1778
2c8b6fdd7a docs: re-shape changelog
* update sorting to reflect more important changes first
* use issue numbers instead of `this issue` wording

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-09 09:39:00 +02:00
Max Kotliar
049768a5ae vmalert: Add link to UI on welcome page. (#8911)
### Describe Your Changes

Add a link to UI on the welcome page.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-09 09:26:34 +02:00
hagen1778
c492dce761 docs: update vmalert's troubleshooting section
* actualize information
* explain alert state in more details
* re-order content by its importance

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-09 09:24:49 +02:00
Aliaksandr Valialkin
e01161b137 docs: added page aliases, which led to 404 error during the last 2 weeks
URLs to these pages exist somewhere in the Internet and they lead to "Page Not Found" errors
according to Google Analytics.

We cannot update these urls to new ones after the f152021521 .
So aliases for these urls must be added.

See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-05-09 02:37:55 +02:00
Aliaksandr Valialkin
4a91070496 docs/victoriametrics/integrations/grafana.md: use the proper link to https://docs.victoriametrics.com/victoriametrics/victoriametrics-datasource/ 2025-05-09 02:27:30 +02:00
Aliaksandr Valialkin
14e38eee90 deployment: update VictoriaLogs Docker image tag from v1.22.0-victorialogs to v1.22.1-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.22.1-victorialogs
2025-05-09 01:39:41 +02:00
Aliaksandr Valialkin
f68a16afa6 docs/victorialogs/CHANGELOG.md: cut v1.22.1-victorialogs release 2025-05-09 01:34:23 +02:00
Aliaksandr Valialkin
3d3294e875 app/vlselect/vmui: run make vmui-logs-update after the commit 0af46a41d7
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8913
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8912
2025-05-09 01:33:20 +02:00
Yury Molodov
0af46a41d7 vmui/logs: fix logs not reloading when query changes (#8913)
### Describe Your Changes

Fix logs not updating after query change
Related issue: #8912

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-09 01:30:42 +02:00
hagen1778
12b589f83a docs: fix images in github readme
The images link was broken after docs re-organization.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-08 20:02:37 +02:00
Aliaksandr Valialkin
3911ca1969 docs/victorialogs/data-ingestion/README.md: add missing chapter for opentelemetry data ingestion HTTP endpoint
This is a follow-up for 01430a155c
2025-05-08 17:39:35 +02:00
Aliaksandr Valialkin
eaaa1c517c deployment: update VictoriaLogs Docker image tag from v1.21.0-victorialogs to v1.22.0-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.22.0-victorialogs
2025-05-08 17:13:01 +02:00
Aliaksandr Valialkin
e1b590c36b docs/victorialogs/CHANGELOG.md: cut v1.22.0-victorialogs release 2025-05-08 17:04:10 +02:00
Aliaksandr Valialkin
e2e1226888 app/vlselect/vmui: run make vmui-logs-update after ad4e4a411e 2025-05-08 17:03:00 +02:00
Aliaksandr Valialkin
623c8abf65 lib/logstorage: add decolorize pipe to LogsQL for removing ANSI color codes from the given log field 2025-05-08 16:50:32 +02:00
Aliaksandr Valialkin
c8cc2434e0 app/vlinsert: add an ability to remove ANSI color codes during data ingestion
ANSI color codes may break or make hard search and analysis of the ingested logs,
so it is a good idea to drop during data ingestion.
2025-05-08 16:50:30 +02:00
Andrii Chubatiuk
60de977fd3 docs: updated removed .Values.externalVM to .Values.external.vm parameter in setup instructions (#8907)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-08 16:00:46 +02:00
Yury Molodov
ad4e4a411e vmui/logs: fix freeze on timeline zoom (#8886)
### Describe Your Changes

Fixes UI freeze in logs timeline after repeated zooming and panning.

The issue was caused by excessive query requests triggered during fast
timeline interactions. Added debounce to limit the frequency of
requests, similar to the approach used in vmui for metrics.

Related issue: #8655

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-08 14:18:40 +02:00
hagen1778
7d199d1d83 docs: mention Integrations and Data Ingestion docs
* tidy up wording
* mention available integrations in quickstart
* cross-reference integrations and data ingestion
* move these docs closer to each other

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-08 14:16:11 +02:00
Yury Molodov
49f23a8755 vmui: limit points and response size on raw query page (#8888)
### Describe Your Changes

Limit number of points per series and total response size (30 MiB) on
the Raw Query page to improve UI stability.
Related issue: #7895

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-08 13:35:10 +02:00
Artur Minchukou
6c51d57c66 lib/promrelabel: update the colors in the Metric Relabel Debug tool to softer tones (#8889)
### Describe Your Changes

Related issue: #8871 
Updated the colors in the Metric Relabel Debug tool to softer tones.

- Light theme: 

<img width="1081" alt="image"
src="https://github.com/user-attachments/assets/de12445e-602b-4a89-9981-3f68f379f780"
/>

- Dark theme: 

<img width="1268" alt="image"
src="https://github.com/user-attachments/assets/fbfcb6c8-4ed8-4015-8c3f-39ed9e4c4645"
/>



### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-08 13:32:42 +02:00
Roman Khavronenko
001dc7c985 deployment: update vlogs demo installation (#8894)
* move example alerts out of /rules folder, since this folder should
contain only useful rules
* expose ports for vlogs and vmetrics for local debug
* add some comments explamining vmalert config

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-08 13:29:10 +02:00
Roman Khavronenko
4745b0c511 app/vmalert: add .Type or $type template variables (#8895)
The new templating option could contain following options: `prometheus`,
`vlogs` or `graphite`.
It represents the datasource type this rule is evaluated against. The
new templating option
can be used in rule's annotations or for routing to a specific
destination (e.g. Grafana datasource).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-08 13:28:34 +02:00
Andrii Chubatiuk
e1630aab4e docs: replace custom anchor heading attribute with id (#8898)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-08 13:21:22 +02:00
Roman Khavronenko
e77df5d00b app/vmauth: expose built-in handlers if -httpInternalListenAddr is specified (#8902)
This functionality was broken in
0e313e5355

Was caught by integration tests:
```
--- FAIL: TestSingleVMAuthRouterWithInternalAddr (5.00s)
    vmauth_routing_test.go:148: Could not start vmauth: could not extract some or all regexps from stderr: ["pprof handlers are exposed at http://(.*:\\d{1,5})/debug/pprof/"]
```

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-08 13:20:38 +02:00
Aliaksandr Valialkin
9b8caebc72 vendor: update github.com/VictoriaMetrics/metrics from v1.34.5 to v1.36.0
This adds PSI metrics to all the VictoriaMetrics processes.

See 255d4dc5c2 for details
2025-05-08 01:31:00 +02:00
Aliaksandr Valialkin
0253dda95a docs/victorialogs/FAQ.md: remove the scary warning that the _msg field is crucial for VictoriaLogs
VictoriaLogs happily accepts logs without _msg field, and there are legitimate cases where the _msg field isn't needed.
Remove the warning in order to reduce the level of confusion for VictoriaLogs users.
2025-05-07 23:57:18 +02:00
Aliaksandr Valialkin
a1a731eb61 app/vlinsert: support comma-separated list of values at _time_field http query arg and at VL-Time-Field HTTP header
This feature is useful when ingesting logs, which may contain timestamps across different fields.
Then the first non-empty field from the _time_field list is used as a timestamp field.
2025-05-07 22:48:21 +02:00
Aliaksandr Valialkin
fec8944ec5 docs/victorialogs/data-ingestion/Promtail.md: clarify that it is recommended leaving enabled JSON message parsing at data ingestion 2025-05-07 20:56:02 +02:00
Aliaksandr Valialkin
fd38860333 docs/victorialogs/LogsQL.md: add String literals chapter, which explains how to quote strings in LogsQL 2025-05-07 20:27:19 +02:00
f41gh7
e1ef768ae8 vendor/metricsql: properly parse quoted label names
This commit updates metricsql lib, which has the following changes:
* parser: properly parse metric name filters with OR modifier
* parser: allow utf-8 quoted label names at IdentList

Related issues:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8826
https://github.com/VictoriaMetrics/metricsql/issues/50

Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-05-07 19:00:00 +02:00
Aliaksandr Valialkin
e848bd6a76 docs: use demo playground instead of playground wording when referring to VictoriaMetrics and VictoriaLogs playgrounds
This is needed in order to be able to find these playgrounds by `demo` word.

While at it, replace misleading `playground` word with less confusing wording across different places of the docs.
2025-05-07 14:54:19 +02:00
Aliaksandr Valialkin
11f7ca7daa all: update Go builder from Go1.24.2 to Go1.24.3
See https://github.com/golang/go/issues?q=milestone%3AGo1.24.3+label%3ACherryPickApproved
2025-05-07 13:26:48 +02:00
hagen1778
d4e1fe38db docs: move NewRelic related docs to Integrations section
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-07 10:55:46 +02:00
hagen1778
e9f65a7b9a docs/integrations: consistently use sh shortcode instead of bash
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-07 09:49:54 +02:00
hagen1778
0a6da3e76a docs: move OpenTSDB related docs to Integrations section
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-07 09:49:16 +02:00
Ted Possible
1b0d535e61 lib/protoparser/prometheus: adds Prometheus 3.0 utf-8 quoted syntax support
This commit properly parses Prometheus 3.0 text exposition format. Which adds new quoted version of metric name and label names with `utf-8` characters.

 See the following doc:
https://github.com/prometheus/proposals/blob/main/proposals/2023-08-21-utf8.md#syntax-examples

Related PR:
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8692
2025-05-06 17:48:36 +02:00
Florian Klink
0e313e5355 lib/httpserver: move ServeWithOpts to Serve
This addresses that todo in the codebase, and updates all callsites to
the new signature.

---------
Signed-off-by: Florian Klink <flokli@flokli.de>
2025-05-06 17:41:44 +02:00
Roman Khavronenko
57164920e3 docs/victoriametrics/quickstart: avoid using word latest
`latest` seem to confuse users with `:latest` tag
see
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7336#issuecomment-2849382265

Replacing it with `newest` word, which is how dockerhub sorts the tags
in its UI at
https://hub.docker.com/r/victoriametrics/victoria-metrics/tags
2025-05-06 17:31:00 +02:00
Andrii Chubatiuk
3b84f45e0a app/{vmagent,vmsingle}: properly init relabel and stream aggr config reload related metrics
Previously  `*_last_reload_successful` metrics are set to 1 even when respective
configuration is not defined, besides stream aggregation and scraping.

 This commit initializes config reload related metrics only when respective
configuration is set.

Related issue:
https://github.com/VictoriaMetrics/helm-charts/issues/2119
2025-05-06 17:29:27 +02:00
f41gh7
cbc2d536c1 packaging/fips: add binaries build in FIPS mode
This commit adds the following changes to the enterprise version:
- add make target for testing in FIPS mode
- disallow using OVH in FIPS mode. OVH is using SHA1 for authentication via headers and SHA1 is not allowed to be used in FIPS mode. There is no option to switch to another hashing algorithm in OVH API, so disabling it completely.
- build fips binaries together with regular ones. This will allow to make sure that FIPS builds are always up to date and compatible with regular ones.
- disable CGO in FIPS builds for vmagent, since vmagent imports Kafka library which uses CGO imports. This might lead to using OpenSSL version which is not certified for FIPS mode. Using pure Go implementation allows to avoid this and keep all validations on Go build process side.
2025-05-06 17:22:16 +02:00
Artem Fetishev
61383e5d80 lib/storage: Add retention filter metrics (#886)
- vm_retention_filtering_partitions_scheduled is a guage metric that shows now
  many partitions the retention filtering is currently being applied to.
- vm_retention_filtering_partitions_scheduled_size_bytes is a guage metric that
  shows the total size (in bytes) of partitions the retention filtering is
  currently being applied to.

These metrics are similar to vm_downsampling_partitions_scheduled and
vm_downsampling_partitions_scheduled_size_bytes and can be used for observing
how much time it took for a given vmstorage instance to perform retention
filtering across this many partitions whose total size was this many bytes.

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
Co-authored-by: Roman Khavronenko <roman@victoriametrics.com>
2025-05-06 15:10:57 +02:00
hagen1778
83a729c2fc docs: move InfluxDB related docs to Integrations section
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-06 14:10:43 +02:00
hagen1778
52da6ba36c docs: move Datadog related docs to Integrations section
Subsections of datadog docs like:
- https://docs.victoriametrics.com/#sending-metrics-to-victoriametrics
- https://docs.victoriametrics.com/#sending-metrics-to-datadog-and-victoriametrics
- https://docs.victoriametrics.com/#send-metrics-via-serverless-datadog-plugin
- https://docs.victoriametrics.com/#send-via-curl
- https://docs.victoriametrics.com/#additional-details

were removed because I didn't find their usage across the docs. Preserving them
would mean keepin meaningless and confusing links like  https://docs.victoriametrics.com/#send-via-curl
or https://docs.victoriametrics.com/#additional-details.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-06 13:38:56 +02:00
Roman Khavronenko
a23c277b04 docs: move Graphite related docs to Integrations section (#8880)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-06 12:04:31 +02:00
Andrii Chubatiuk
ac414d8b93 docs: fixed typos (#8878)
### Describe Your Changes

fixed typos in docs and code
fixed collision in cloud docs

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-06 12:03:56 +02:00
f41gh7
0a4e7912fd {lib/backup,app/}: gracefully cancel currently running operation during graceful shutdown
* {lib/backup,app/}: gracefully cancel currently running operation during graceful shutdown

Make backup/restore process interruptable by passing global context from the operation caller.

This is needed in order to reduce shutdown delays in case backup/restore cancellation is requested.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8554
2025-05-06 12:00:51 +02:00
Zakhar Bessarab
bc7dd85ae9 app/vmbackupmanager: add backup state to backups listing
Include backup completion state at `/api/v1/backups` and CLI command in order to make it easier to discover incomplete backups when performing a restore.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5361
2025-05-06 12:00:21 +02:00
Phuong Le
d9cc16772e lib/logstorage: fix infinite loop and anchor misbehavior in replace_regexp
This PR fixes two related bugs in the `replace_regexp` pipe:


1. **Infinite loop on empty matches when `limit` is not set**
[#8625](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8625)
When a regex pattern like `\d*`, `()`, or `\b` was used, the
implementation could repeatedly match the same zero-width position
without advancing the string, causing unbounded memory usage and
eventual OOM. This is now fixed by collecting all matches up front,
respecting the `limit`, and applying replacements in a single pass.

2. **Incorrect handling of anchors (`^` and `$`)**  
The previous implementation applied regex matching to progressively
sliced substrings (`s = s[end:]`), which unintentionally caused anchor
patterns like `^` (start-of-string) to match at every new substring's
start. As a result, patterns that should have matched only once (e.g.,
`^|$`) ended up matching multiple times.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8625
2025-05-06 11:17:10 +02:00
Vadim Alekseev
fdf530d6ab app/vlinsert: better error reporting in the /jsonline handler
This commit improves error messages in the /jsonline handler by
returning a 400 Bad Request if all the JSON lines were invalid.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8818
2025-05-06 11:11:24 +02:00
Aliaksandr Valialkin
7c7439a4e0 docs/victorialogs/cluster.md: pay attention that vlinsert spreads incoming logs _evenly_ among vlstorage nodes
Hopefully this should reduce the amounts of questions whether vlinsert replicates or shards the incoming logs.
The answer - it spreads the incoming log _evenly_ among the configured vlstorage nodes (e.g. it shards logs).
2025-05-05 22:08:44 +02:00
Aliaksandr Valialkin
3e462b3687 docs: replace https://docs.victoriametrics.com#... with https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#...
This avoids redirect from https://docs.victoriametrics.com#... to https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#...
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-05-05 20:40:27 +02:00
Aliaksandr Valialkin
411d651cca docs/victorialogs/README.md: remove the link to https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/dashboards/victorialogs-cluster.json , since https://grafana.com/grafana/dashboards/23274 is already approved by Grafana 2025-05-05 20:37:13 +02:00
jmehrs
84163a56eb lib/httpserver: add -http.disableCORS flag for disabling CORS (#8684)
### Changes

Updated `lib/httpserver/httpserver.go` to include a flag that can toggle
CORS (defaults to true to keep the current behavior).

This PR relates to
[this](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8680#issue-2983786438)
feature request

### Checklist

The following checks are **mandatory**:

- [x] My change does not break backwards compatibility (i.e., preserves
CORS being enabled unless specified otherwise via the
`-http.cors.disabled=true` flag & value)

---------

Co-authored-by: Jai Mehra <jai.mehra@nav-timing.safrangroup.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-05-05 20:06:22 +02:00
Evgeny
d85bb968c0 app/vmalert-tool: allow parsing Inf values and scientific notation (#8847)
### Describe Your Changes

#8842 
As a quick fix, it seems like it works. checked on my failing tests
(they are not emitting this error anymore)

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Co-authored-by: Roman Khavronenko <hagen1778@gmail.com>
2025-05-05 19:54:36 +02:00
Jose Gómez-Sellés
1f980c5956 Add text to cloud integrations (#8876) 2025-05-05 18:47:58 +02:00
Artem Fetishev
d33d7e20be lib/storage: Add more unit tests and benchmarks (#8848)
These were added while working on paritition index (#8134). Submitting
the separately in order to:

1. Make sure partition index will not break anything and
2. Be able to compare performance before and after swiching to parition
index.

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-05 17:13:06 +02:00
Roman Khavronenko
6ec422160b docs: add integration page (#8870)
The rationale behind this change was explained here
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2841788436

This PR moves only Prom and Grafana docs to show the change and limit
the amount of changes across docs.
Once accepted, the follow-up PRs will move Graphite, InfluxDB, OpenTSDB,
Datadog and NewRelic docs.

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-05 15:32:44 +02:00
Andrii Chubatiuk
6e6d0b35c8 app/vmalert: follow-up for https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8750 (#8875)
fixed not successful rebase in PR, moved svg icons to a sprite and added
VM logo to UI

<img width="1290" alt="image"
src="https://github.com/user-attachments/assets/34cfdc61-6349-4320-b133-38965cb6c30f"
/>


### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-05 15:31:47 +02:00
pkucode
41abe16adc refactor: use the built-in max/min to simplify the code (#8609)
### Describe Your Changes

use the built-in max/min to simplify the code

### Checklist

The following checks are **mandatory**:

- [x] My change adheres [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

Signed-off-by: pkucode <cssjtu@163.com>
2025-05-05 15:31:29 +02:00
Roman Khavronenko
b5c9284748 deployment/rules: add alerting rule ScrapePoolHasNoTargets to vmagent (#8868)
The new rule should notify user when there is a job with 0 configured or
discovered targets, which is usually a sign of misconfiguration.

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-05 15:14:56 +02:00
Roman Khavronenko
1bfe574401 docs/victorialogs/quickstart: fix typo in link to cluster helm chart (#8874)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-05 15:14:29 +02:00
Hui Wang
16f7eef5d5 doc: mention distributed chart in HA section (#8846)
https://github.com/VictoriaMetrics/helm-charts/issues/2153

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-05-05 15:14:15 +02:00
Artem Fetishev
f9d8cc2708 Follow-up for #8596: fix regression integration tests for cluster
Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-05-05 14:33:33 +02:00
Zhu Jiekun
fcc1f7b981 replace app/victoria-metrics/main_test with apptest (#8596)
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8466

This pull request:
1. Add `GraphiteWrite`, `CSVImport`, `OpenTSDBHTTPImport` data import
methods for vmsingle and vminsert.
2. Add TCP `Write` method to `apptest.Client` to make it capable of
writing data in TCP-based protocol.
3. Add test cases:
    1. for new import methods.
    2. for corner cases placed under `app/victoria-metrics/main_test`.
4. Removed all test cases under `app/victoria-metrics/main_test`.

Signed-off-by: f41gh7 <nik@victoriametrics.com>
Co-authored-by: f41gh7 <nik@victoriametrics.com>
2025-05-05 12:58:45 +02:00
Fred Navruzov
6a267a80be docs/vmanomaly - adjust note section to new formatting (#8865)
### Describe Your Changes

Updated "> note" sections in /anomaly-detection/ doc path for new
formatting and improved clarity

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/).
2025-05-01 22:48:25 +02:00
hagen1778
25cd945d9b docs/victorialogs: mention cluster helm chart
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-01 20:45:42 +02:00
hagen1778
804bf2371b docs: mention 90d2a6e author
Signed-off-by: hagen1778 <roman@victoriametrics.com>
(cherry picked from commit afbe2e6c86)
2025-05-01 20:30:23 +02:00
hagen1778
930da160af docs: mention 90d2a6e in vmalert docs
Signed-off-by: hagen1778 <roman@victoriametrics.com>
(cherry picked from commit 79f5c4ed12)
2025-05-01 20:30:22 +02:00
Emre Yazıcı
f2069a0bc7 app/vmalert: add debug to rule.Group (#8658)
### Describe Your Changes

app/vmalert feat: add Debug to rule.Group

This is to enable/disable debug logs for the rules at group level.
Default is false.

Rule specific `debug` configuration takes priority over group level
configuration.

Relates to [app/vmalert: chore: log when response is
partial](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8522)

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: emreya <e.yazici1990@gmail.com>
Signed-off-by: Emre Yazici <e.yazici1990@gmail.com>
Signed-off-by: emreya <emre.yazici@adyen.com>
Co-authored-by: Hui Wang <haley@victoriametrics.com>
Co-authored-by: Roman Khavronenko <roman@victoriametrics.com>
(cherry picked from commit 90d2a6efed)
2025-05-01 20:30:22 +02:00
hagen1778
1cca22f88d app/vmalert: replace backticks with single quotes in flag description
This is needed because Go interprets backticked string as a measurement unit for the given command-line flag:

    The listed type, here int, can be changed by placing a back-quoted name in the flag's usage string;
    the first such item in the message is taken to be a parameter name to show in the message and the back quotes
    are stripped from the message when displayed

See https://pkg.go.dev/flag#PrintDefaults

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-05-01 13:13:06 +02:00
Aliaksandr Valialkin
cafb847544 docs/victorialogs/logql-to-logsql.md: typo fix: Sotring -> Storing 2025-05-01 00:17:29 +02:00
Aliaksandr Valialkin
b9f080321c docs/victoriametrics/Cluster-VictoriaMetrics.md: update -help output for vmselect, vminsert and vmstorage using Enterprise version 2025-04-30 23:34:01 +02:00
Aliaksandr Valialkin
0ffbca2f92 docs/victoriametrics/vmrestore.md: update ./vmrestore -help output using Enterprise version 2025-04-30 23:28:34 +02:00
Aliaksandr Valialkin
0f3d15c573 docs/victoriametrics/vmbackup.md: update ./vmbackup -help output using Enterprise version 2025-04-30 23:28:34 +02:00
Aliaksandr Valialkin
8f58b58bd3 docs/victoriametrics/vmauth.md: update ./vmauth -help output using Enterprise version 2025-04-30 23:28:33 +02:00
Aliaksandr Valialkin
3b182de3e2 docs/victoriametrics/vmalert.md: update ./vmalert -help output using Enterprise version 2025-04-30 23:28:33 +02:00
Aliaksandr Valialkin
d659017408 docs/victoriametrics/vmagent.md: update ./vmagent -help output using Enterprise version 2025-04-30 23:28:32 +02:00
Aliaksandr Valialkin
304b2d4625 docs/victoriametrics/README.md: update ./victoria-metrics -help output using Enterprise version 2025-04-30 23:28:32 +02:00
Aliaksandr Valialkin
aeb5d69fa5 app/{vmselect,vlselect}/vmui: run make vmui-update vmui-logs-update after 492def6d57 2025-04-30 23:03:56 +02:00
Aliaksandr Valialkin
a6b2776b0c use new canonical urls to vmgateway docs: https://docs.victoriametrics.com/victoriametrics/vmgateway/
This avoids a redirect from the old link https://docs.victoriametrics.com/vmgateway/ to https://docs.victoriametrics.com/victoriametrics/vmgateway/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 23:00:37 +02:00
Aliaksandr Valialkin
ada6466f45 use new canonical urls to victoriametrics-datasource docs: https://docs.victoriametrics.com/victoriametrics/victoriametrics-datasource/ 2025-04-30 22:55:02 +02:00
Aliaksandr Valialkin
a05954884d use new canonical urls to url-examples docs: https://docs.victoriametrics.com/victoriametrics/url-examples/
This avoids a redirect from the old link https://docs.victoriametrics.com/url-examples/ to https://docs.victoriametrics.com/victoriametrics/url-examples/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 22:51:54 +02:00
Aliaksandr Valialkin
e446e1a2e0 use new canonical urls to stream-aggregation docs: https://docs.victoriametrics.com/victoriametrics/stream-aggregation/
This avoids a redirect from the old link https://docs.victoriametrics.com/stream-aggregation/ to https://docs.victoriametrics.com/victoriametrics/stream-aggregation/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 22:47:13 +02:00
Aliaksandr Valialkin
1303b91953 use new canonical urls to single-server-victoriametrics docs: https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/
This avoids a redirect from the old link https://docs.victoriametrics.com/ to https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 22:31:37 +02:00
Aliaksandr Valialkin
f7efa0563e use new canonical urls to single-server-victoriametrics docs: https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/
This avoids a redirect from the old link https://docs.victoriametrics.com/single-server-victoriametrics/ to https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 21:44:02 +02:00
Aliaksandr Valialkin
7e1ea66321 use new canonical urls to scrape_config_examples docs: https://docs.victoriametrics.com/victoriametrics/scrape_config_examples/
This avoids a redirect from the old link https://docs.victoriametrics.com/scrape_config_examples/ to https://docs.victoriametrics.com/victoriametrics/scrape_config_examples/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 21:31:36 +02:00
Aliaksandr Valialkin
1824828d07 use new canonical urls to relabeling docs: https://docs.victoriametrics.com/victoriametrics/relabeling/
This avoids a redirect from the old link https://docs.victoriametrics.com/relabeling/ to https://docs.victoriametrics.com/victoriametrics/relabeling/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 21:28:50 +02:00
Aliaksandr Valialkin
3f483318d8 app/vmselect/prometheus: use the correct url to tsdb stats docs at the description for the -search.maxTSDBStatusTopNSeries command-line flag
This is a follow-up for the commit d47d329ce7

See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/7973
and https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6898
2025-04-30 20:56:41 +02:00
Aliaksandr Valialkin
8b28dfe566 use new canonical urls to quick-start docs: https://docs.victoriametrics.com/victoriametrics/quick-start/
This avoids a redirect from the old link https://docs.victoriametrics.com/quick-start/ to https://docs.victoriametrics.com/victoriametrics/quick-start/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 20:23:09 +02:00
Aliaksandr Valialkin
8172e4b7ea use new canonical urls to query-stats docs: https://docs.victoriametrics.com/victoriametrics/query-stats/
This avoids a redirect from the old link https://docs.victoriametrics.com/query-stats/ to https://docs.victoriametrics.com/victoriametrics/query-stats/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 20:20:04 +02:00
Aliaksandr Valialkin
09168739f8 use new canonical urls to pertenantstatistic docs: https://docs.victoriametrics.com/victoriametrics/pertenantstatistic/
This avoids a redirect from the old link https://docs.victoriametrics.com/pertenantstatistic/ to https://docs.victoriametrics.com/victoriametrics/pertenantstatistic/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 20:16:44 +02:00
Aliaksandr Valialkin
ee2205c85b use new canonical urls to lts-releases docs: https://docs.victoriametrics.com/victoriametrics/lts-releases/
This avoids a redirect from the old link https://docs.victoriametrics.com/lts-releases/ to https://docs.victoriametrics.com/victoriametrics/lts-releases/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 20:12:00 +02:00
Aliaksandr Valialkin
5383fec238 use new canonical urls to keyconcepts docs: https://docs.victoriametrics.com/victoriametrics/keyconcepts/
This avoids a redirect from the old link https://docs.victoriametrics.com/keyconcepts/ to https://docs.victoriametrics.com/victoriametrics/keyconcepts/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 20:08:42 +02:00
Aliaksandr Valialkin
556076f899 use new canonical urls to faq docs: https://docs.victoriametrics.com/victoriametrics/faq/
This avoids a redirect from the old link https://docs.victoriametrics.com/faq/ to https://docs.victoriametrics.com/victoriametrics/faq/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 19:59:07 +02:00
Aliaksandr Valialkin
e39914c189 use new canonical urls to enterprise docs: https://docs.victoriametrics.com/victoriametrics/enterprise/
This avoids a redirect from the old link https://docs.victoriametrics.com/enterprise/ to https://docs.victoriametrics.com/victoriametrics/enterprise/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 19:15:19 +02:00
Aliaksandr Valialkin
a02ef7933a use new canonical urls to data-ingestion docs: https://docs.victoriametrics.com/victoriametrics/data-ingestion/
This avoids a redirect from the old link https://docs.victoriametrics.com/data-ingestion/ to https://docs.victoriametrics.com/victoriametrics/data-ingestion/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 19:08:01 +02:00
Aliaksandr Valialkin
7a9cbcdbed use new canonical urls to contributing docs: https://docs.victoriametrics.com/victoriametrics/contributing/ 2025-04-30 19:03:45 +02:00
Aliaksandr Valialkin
e5fd16f343 use new canonical urls to cluster-victoriametrics docs: https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/
This avoids a redirect from the old link https://docs.victoriametrics.com/cluster-victoriametrics/ to https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 18:52:12 +02:00
Aliaksandr Valialkin
ba4dca8e5f use new canonical urls to changelog docs: https://docs.victoriametrics.com/victoriametrics/changelog/
This avoids a redirect from the old link https://docs.victoriametrics.com/changelog/ to https://docs.victoriametrics.com/victoriametrics/changelog/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 18:39:18 +02:00
Aliaksandr Valialkin
e1c273ec56 use new canonical urls to casestudies docs: https://docs.victoriametrics.com/victoriametrics/casestudies/
This avoids a redirect from the old link https://docs.victoriametrics.com/casestudies/ to https://docs.victoriametrics.com/victoriametrics/casestudies/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 18:27:31 +02:00
Aliaksandr Valialkin
ed4ffc5b53 use new canonical urls to bestpractices docs: https://docs.victoriametrics.com/victoriametrics/bestpractices/
This avoids a redirect from the old link https://docs.victoriametrics.com/bestpractices/ to https://docs.victoriametrics.com/victoriametrics/bestpractices/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 18:24:18 +02:00
Aliaksandr Valialkin
58a605317f use new canonical urls to articles docs: https://docs.victoriametrics.com/victoriametrics/articles/
This avoids a redirect from the old link https://docs.victoriametrics.com/articles/ to https://docs.victoriametrics.com/victoriametrics/articles/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 17:43:14 +02:00
Aliaksandr Valialkin
5e76845b5d use new canonical urls to sd_configs docs: https://docs.victoriametrics.com/victoriametrics/sd_configs/
This avoids a redirect from the old link https://docs.victoriametrics.com/sd_configs/ to https://docs.victoriametrics.com/victoriametrics/sd_configs/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 17:40:33 +02:00
Aliaksandr Valialkin
f587771c4a use new canonical urls to troubleshooting docs: https://docs.victoriametrics.com/victoriametrics/troubleshooting/
This avoids a redirect from the old link https://docs.victoriametrics.com/troubleshooting/ to https://docs.victoriametrics.com/victoriametrics/troubleshooting/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 17:32:16 +02:00
Aliaksandr Valialkin
6392c0a0cb use new canonical urls to metricsql docs: https://docs.victoriametrics.com/victoriametrics/metricsql/
This avoids a redirect from the old link https://docs.victoriametrics.com/metricsql/ to https://docs.victoriametrics.com/victoriametrics/metricsql/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 17:24:39 +02:00
Aliaksandr Valialkin
5188436b14 all: use new canonical urls to vmrestore docs: https://docs.victoriametrics.com/victoriametrics/vmrestore/
This avoids a redirect from the old link https://docs.victoriametrics.com/vmrestore/ to https://docs.victoriametrics.com/victoriametrics/vmrestore/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 16:55:29 +02:00
Aliaksandr Valialkin
acd06e37a8 all: use new canonical urls to vmbackup docs: https://docs.victoriametrics.com/victoriametrics/vmbackup/
This avoids a redirect from the old link https://docs.victoriametrics.com/vmbackup/ to https://docs.victoriametrics.com/victoriametrics/vmbackup/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 16:51:30 +02:00
Aliaksandr Valialkin
e50ccee5ac all: use new canonical urls to vmbackupmanager docs: https://docs.victoriametrics.com/victoriametrics/vmbackupmanager/
This avoids a redirect from the old link https://docs.victoriametrics.com/vmbackupmanager/ to https://docs.victoriametrics.com/victoriametrics/vmbackupmanager/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 16:47:21 +02:00
Aliaksandr Valialkin
92bf019c3d all: use new canonical urls to vmctl docs: https://docs.victoriametrics.com/victoriametrics/vmctl/
This avoids a redirect from the old link https://docs.victoriametrics.com/vmctl/ to https://docs.victoriametrics.com/victoriametrics/vmctl/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 16:43:48 +02:00
Aliaksandr Valialkin
4261b28c86 all: use new canonical urls to vmauth docs: https://docs.victoriametrics.com/victoriametrics/vmauth/
This avoids a redirect from the old link https://docs.victoriametrics.com/vmauth/ to https://docs.victoriametrics.com/victoriametrics/vmauth/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 16:40:01 +02:00
Aliaksandr Valialkin
589ee65c83 lib/atomicutil: rename Slice.GetSlice to Slice.All for the sake of better readability 2025-04-30 16:13:57 +02:00
Aliaksandr Valialkin
46ec5e1d11 all: use new canonical urls to vmalert docs: https://docs.victoriametrics.com/victoriametrics/vmalert/
This avoids a redirect from the old link https://docs.victoriametrics.com/vmalert/ to https://docs.victoriametrics.com/victoriametrics/vmalert/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 16:02:45 +02:00
Aliaksandr Valialkin
41356d4e3e all: use new canonical urls to vmagent docs: https://docs.victoriametrics.com/victoriametrics/vmagent/
This avoids a redirect from the old link https://docs.victoriametrics.com/vmagent/ to https://docs.victoriametrics.com/victoriametrics/vmagent/ ,
and fixes `backwards` navigation for these links across VictoriaMetrics docs.

This is a follow-up for f152021521
See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595#issuecomment-2831598274
2025-04-30 13:24:39 +02:00
Aliaksandr Valialkin
7d1294e080 docs/victorialogs/logql-to-logsql.md: typo fixes and small clarifications 2025-04-30 13:02:51 +02:00
Aliaksandr Valialkin
045f33bcc3 docs/victorialogs/data-ingestion/README.md: clarify what is the vl_http_errors_total{path="/insert/jsonline"} counter 2025-04-30 11:51:32 +02:00
Aliaksandr Valialkin
ee81975392 docs/victorialogs/data-ingestion/README.md: document that VictoriaLogs skips invalid JSON lines and continues parsing the remaining lines at /insert/jsonline API
This clarifies the behaviour for /insert/jsonline for invalid JSON lines.
2025-04-30 11:47:21 +02:00
Aliaksandr Valialkin
039411e012 docs/victorialogs: add a guide for converting Loki query to VictoriaLogs query - https://docs.victoriametrics.com/victorialogs/logql-to-logsql/ 2025-04-29 22:50:50 +02:00
Aliaksandr Valialkin
cc274cf079 docs/victorialogs/FAQ.md: add a link to the article explaining why VictoriaLogs is better than Loki to the What is the difference between Loki and VictoriaLogs? question 2025-04-29 18:13:18 +02:00
Aliaksandr Valialkin
28a7840ad2 docs/victorialogs/LogsQL.md: clarify that by default LogsQL filters return matching logs with all the fields, not only the _msg field 2025-04-29 18:03:35 +02:00
Aliaksandr Valialkin
a1ade47591 docs/victorialogs/LogsQL.md: update misleading outdated docs about parse() function - it is named extract pipe now 2025-04-29 17:58:26 +02:00
Yury Molodov
492def6d57 vmui/logs/fix sorting issues (#8816)
### Describe Your Changes

1. Fixed log entry sorting in the "Group" view: newest entries are now
displayed at the top again. In v1.18.0, log entries were incorrectly
sorted (oldest first) due to changes related to nanosecond precision
support.
    Related issue: #8726
2. Added alphabetical sorting of fields by key in the "Group" view for
easier navigation.
    Related issue: #8438

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-04-29 11:58:53 +02:00
Andrii Chubatiuk
7b675bfc13 app/vmalert: upgraded bootstrap, removed jquery, fixed collapse issues (#8750)
### Describe Your Changes

upgraded bootstrap, removed jquery, fixed UI collapse issues in vmalert
UI

<img width="967" alt="image"
src="https://github.com/user-attachments/assets/adcd0a74-fd33-4ec6-b2ee-9e642bcf8425"
/>
<img width="528" alt="image"
src="https://github.com/user-attachments/assets/ecf4f1f7-ec05-4d01-a423-516076cb3d30"
/>


### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: Roman Khavronenko <roman@victoriametrics.com>
2025-04-29 11:46:18 +02:00
hagen1778
75a970fb5e docs: tidy up QuickStart doc
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-29 11:41:27 +02:00
hagen1778
c1b9b2bd8b docs: add link to benchmark results to vmctl migration between VMs
While there, remove version requirements for VM migration as it
is almost 4y old by now.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-29 11:30:37 +02:00
Alexander Marshalov
5d12ba702e vmcloud: small fixes in access tokens docs (#8832)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-29 09:19:18 +02:00
Artur Minchukou
d6efa6365d app/vmui: rename flag retentionFilters to retentionFilter in retention-filter-debug example
### Describe Your Changes

Related issue: #8697 

Renamed `retentionFilters` to `retentionFilter`.

🛑 before merge this pull request, need to merge API changes in
enterprise version.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-29 10:47:48 +04:00
Artur Minchukou
767c0cc996 app/vmselect: rename parameter retentionFilters to retentionFilter 2025-04-29 10:46:19 +04:00
Amin Cheloh
f0f548231d docs: fix typos in victorialogs FAQ.md (#8821)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-28 15:47:49 +02:00
hagen1778
5147846d18 dashboards: update Query Stats
* set Y-min to 0. This helps to see real spikes in resource usage;
* add text panel explaining how to use query hash;
* support filtering by tenant;
* use `\tvm_slow_query_stats` prefix filter to filter out logs
 that mention failed queries with `vm_slow_query_stats` word;
* add panel to show the minimum queried timestamp - see https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8828

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-28 15:46:02 +02:00
f41gh7
dab3ed4056 docs: mention LTS releases at changelog
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-04-28 14:28:08 +03:00
f41gh7
e0254b996a docs: update vm apps to v1.116.0
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-04-28 14:27:58 +03:00
f41gh7
1d30efa48f make docs-update-version 2025-04-28 14:25:05 +03:00
f41gh7
bf88327121 CHANGELOG.md: cut v1.116.0 release 2025-04-28 14:20:12 +03:00
hagen1778
a6d68f859f docs: improve wording of query stats
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-28 13:02:48 +02:00
Artem Fetishev
b911f721b3 docs: Fix the definition of active time series (#8824)
Based on the code, an active time series is one that has received at
least one sample during the last hour. It does not includes querying.

The first time the docs were updated with this was in
d06aae9454. But even at that time, the
code shows that querying a metric did not make it active.



- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-04-28 12:11:47 +02:00
hagen1778
3f39bd08cf docs: tidy up last changelog
* put important changes on top;
* replace `this issue` with corresponding issue number to make it more sense;
* consistently format components names.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-28 09:02:06 +02:00
Alexander Marshalov
cddf36af43 vmcloud docs: add information about access tokens (#8780)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Co-authored-by: Jose Gómez-Sellés <14234281+jgomezselles@users.noreply.github.com>
2025-04-27 21:40:40 +02:00
hagen1778
0e555b421d dashboards: update query stats
* display max values instead of cumulative values
to outline anomalies;
* remove unnecessary overrides on column width;
* add corresponding formatting units to displayed values.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-27 17:34:26 +02:00
Aliaksandr Valialkin
ec6f33f526 lib/logstorage: prevent from slow memory leak at datadb.rb
datadb.rb contains logRows shards, which weren't freed up after the data ingestion
for the given per-day datadb is stopped. This leads to slow memory leak when VictoriaLogs runs
for multiple days without restarts. Avoid this memory leak by freeing up the logRows shards
after converting them to in-memory parts. Re-use the freed up logRows shards via a pool in order
to reduce the pressure on GC.
2025-04-26 22:40:32 +02:00
Aliaksandr Valialkin
e316ab878c all: fix broken links to *.md files inside docs package after the commit f152021521
This commit moved all the docs/*.md files to docs/victoriametrics/ folder. This broke direct links to these files
such as https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/docs/vmagent.md .
Add the missing `/victoriametrics/` part here, so the link becomes https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/docs/victoriametrics/vmagent.md .

The move of all the docs/*.md files into docs/victoriametrics/ folder is dubious because of the following reasons:

- It breaks direct links to *.md files like mentioned above. It is impossible to fix such links all over the Internet,
  so they will remain broken :(
  The best thing we can do is to fix them on the resources we control such as VictoriaMetrics repository.

- It breaks Google indexing of VictoriaMetrics docs. Google index contains old links such as https://docs.victoriametrics.com/vmagent/#features .
  Now such links are automatically redirected to https://docs.victoriametrics.com/victoriametrics/vmagent/#features by a javascript on the https://docs.victoriametrics.com/vmagent/ page.
  Google doesn't like redirects at javascript, since they are frequently used by black hat SEO purposes. This leads to pessimization of VictoriaMetrics docs
  in Google search result :( We cannot update the old links all over the Internet in order to avoid the redirect by javascript :(
  The best thing we can do is to add <meta rel="canonical"> header with the new location of the page at the old url,
  and hope Google won't remove VictoriaMetrics docs from its search results. @AndrewChubatiuk , please do this.

- It breaks backwards navigation. When you click the https://docs.victoriametrics.com/vmagent/ link on some page and then press `back` button
  in the web browser, it won't return back you to the original page because of the intermediate redirect :( The broken navigation cannot be fixed
  for old links located all over the Internet.

- It increases chances of breaking old links left on the Internet in the future, which will lead to 404 Not Found pages
  and angry users :(

The sad thing is that we hit the same wall with harmful redirects again :( In the beginning the VictoriaMetrics docs links had .html suffix,
and they were case-sensitive. For example, http://docs.victoriametrics.com/MetricsQL.html#rate . It has been decided for some unknown reason
that it is a good idea to remove the .html suffix and to make all the links lowercase. So now such links are automatically redirected by javascript
to https://docs.victoriametrics.com/metricsql/#rate and then redirected again by another javasript to https://docs.victoriametrics.com/victoriametrics/metricsql/#rate :(
There are many old links all over the Internet (for example, at Reddit, StackOverflow, some internal Wiki pages, etc.). We cannot fix all of them,
so we need to pray these links won't break in the future.

@hagen1778, @tenmozes, @makasim , please make sure we won't hit the same wall in a third time.

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8595
2025-04-26 00:52:24 +02:00
Aliaksandr Valialkin
4aa0f93085 docs/victoriametrics/Articles.md: add a link to https://blog.ogenki.io/post/series/observability/alerts/ 2025-04-26 00:26:42 +02:00
Aliaksandr Valialkin
764fc6010d vendor: run make vendor-update 2025-04-25 23:25:32 +02:00
Aliaksandr Valialkin
3ec70a4b6d Makefile: run go mod tidy with -compat=1.24 instead of -compat=1.23
VictoriaMetrics source code depends on Go 1.24, so it is better to run `go mod tidy` in Go 1.24 compatibility mode.
2025-04-25 23:16:57 +02:00
Aliaksandr Valialkin
3b7039679f lib/logstorage: make golangc-lint happy by substituting unused function arg with _ 2025-04-25 23:14:36 +02:00
Aliaksandr Valialkin
f3197dc5d7 deployment: update VictoriaLogs Docker image tags from v1.20.0-victorialogs to v1.21.0-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.21.0-victorialogs
2025-04-25 19:48:48 +02:00
Aliaksandr Valialkin
9d82de9385 docs/victorialogs: cut v1.21.0-victorialogs 2025-04-25 19:41:56 +02:00
Aliaksandr Valialkin
c34f6db5c0 app/vlselect/vmui: run make vmui-logs-update after 202fc0652c 2025-04-25 19:40:42 +02:00
Aliaksandr Valialkin
8ad81220d3 lib/logstorage: increase scalability of datadb.mustAddRows() on hosts with many CPU cores
Use multiple independent logRows shards for storing the pending log entries before converting them to searchable parts.
Every shard is protected by its own mutex, so multiple CPU cores may add multiple log rows into datadb at the same time.

This increases the performance of BenchmarkStorageMustAddRows/rowsPerInsert-1, which ingests log rows own-by-one
from concurrently running goroutines, by 2x.
2025-04-25 19:35:33 +02:00
Aliaksandr Valialkin
7455e6c0a5 lib/logstorage: re-use newTestLogRows() for creating LogRows inside BenchmarkStorageMustAddRows 2025-04-25 19:35:32 +02:00
Alexander Marshalov
22c85a149e vmcloud docs: add intergrations section (#8744)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-25 19:28:47 +02:00
f41gh7
1e4238ede7 make vmui-update 2025-04-25 15:51:11 +03:00
Jose Gómez-Sellés
1d218f6aeb docs/cloud: add organizations documents (#8814)
Here a description of important terms related to Organizations is
provided. The intention is to leverage on a good UI design rather than
explaining all steps needed to perfomr certain actions.

However, an effort on explaining the meaning of internal states and
terms has been done.

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-25 14:32:21 +02:00
f41gh7
ba4c9133ee lib/handshake: log client network errors during handshake as warnings
This commit modifies the logging behavior for client network errors
(e.g., EOFs, timeouts) during the handshake process. They are now logged
as warnings instead of errors, as they are not actionable from the
server’s perspective. Here's some examples of such errors.

Timeouts during the initial read phase:

2025-04-09T07:08:59.323Z	error
VictoriaMetrics/lib/vmselectapi/server.go:204	cannot perform
vmselect handshake with client "<REDACTED>": cannot read hello: cannot
read message with size 11: read tcp4 <REDACTED>-><REDACTED>: i/o
timeout; read only 0 bytes

EOFs occurring later in the handshake process:

2025-04-08T18:01:30.783Z	error
VictoriaMetrics/lib/vmselectapi/server.go:204	cannot perform
vmselect handshake with client "<REDACTED>": cannot read isCompressed
flag: cannot read message with size 1: EOF; read only 0 bytes

By logging these as warnings, we reduce noise in error logs while
preserving valuble information for debug.
2025-04-25 12:03:03 +03:00
Nikolay
dcadc65681 lib/cgroup: properly parse cpu limit
Previously, if `cpu.max` file has only `max` resource defined without
`period`, it was parsed incorrectly and silently drop error. While this
syntax is valid and actually used by some container runtimes. If period
is not defined, default value for it 100_000 must be used.

 This commit fixes parsing function by using default value for period.
In addition, it adds zero value check, which fixes possible panic if
period has 0 value.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8808
2025-04-25 11:48:05 +03:00
Zhu Jiekun
ae9126fae7 changelog: fix update note & sort upcomming changelog
sort the upcoming changelog in alphabet order.
2025-04-25 11:38:09 +03:00
hagen1778
bf3b98954e docs: tidy up changelog before release
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-25 10:03:30 +02:00
Andrii Chubatiuk
814a37e57e docs: fixed docs-debug target (#8791)
### Describe Your Changes

related https://github.com/VictoriaMetrics/vmdocs/issues/129

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-25 09:39:18 +02:00
f41gh7
0afa51a156 fixes test after 1572e1e5c3 2025-04-24 23:32:37 +03:00
Max Kotliar
b89cce6bd6 docs\stream-aggregation: Describe dropping unneeded labels in more details
Follow-up on
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8715 and
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8681#issuecomment-2796127921
2025-04-24 20:26:37 +03:00
Artur Minchukou
fdfa68bc2d app/vmui/logs: fix zoom behavior on VictoriaLogs chart
Fix zoom behavior on VictoriaLogs chart. The problem was that after
zooming, the chart was recreated and the cursor position on the graph
was lost, so further zooming occurred relative to the zero position. So
to fix this problem:
- removed unnecessary dependencies from useEffect to avoid recreating
the chart;
- moved the chart with the legend to a separate component to optimize
the code when the graph is hidden;
- also this PR contains changes from [this
PR](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8718), which
preserve zoom selection on autorefresh

Related issues:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8557
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8558
2025-04-24 20:25:48 +03:00
Zhu Jiekun
1572e1e5c3 app/vmagent: add consistent hashing for the remote write sharding
This commit adds the following changes:
* use consistent hashing  for the remote write sharding.
* properly count metric of remote write samples drop rate  when `shardByURL` was
enabled.

Related issues:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8546
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8702
2025-04-24 20:22:59 +03:00
Aliaksandr Valialkin
55d75b911c app/vlstorage: add /internal/force_flush endpoint for flusing all the recently ingested logs to searchable parts
This endpoint is needed for integration tests, which need querying the recently ingested logs.
2025-04-24 18:17:30 +02:00
Aliaksandr Valialkin
f9e312f35a app/vlselect/logsql: allow passing multiple extra_filters and extra_stream_filters query args to all the querying APIs
This should help the proper implementation of extra filters in VictoriaLogs Plugin for Grafana and
in VictoriaLogs web UI. See https://github.com/VictoriaMetrics/victorialogs-datasource/issues/293#issuecomment-2827285583
2025-04-24 17:55:33 +02:00
Aliaksandr Valialkin
0cfe28c2fc Revert "ci: temporary disable vlogs tests for i386 "
This reverts commit fa6a32a39d.

Reason for revert: the broken tests were fixed on GOARCH=386 by skipping the check for the state size
after improting the state of stats function, since the state size depends on the hardware architecture.

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8710
2025-04-24 17:31:40 +02:00
Yury Molodov
1c39853164 vmui: show read usage in Cardinality Explorer (#8757)
### Describe Your Changes

Two new columns were added to the **Cardinality Explorer** table:

`Requests count`
- Displays how many times a metric was queried since stats collection
began
- Highlighted **red** when the value is `0` or missing

`Last request`
- Shows when the metric was last queried
- Highlighted:
  - **Red** if older than **30 days**
  - **Yellow** if between **7 and 30 days**
- Shows exact timestamp on hover in `YYYY-MM-DD HH:mm:ss` format

Related issue: #6145


![image](https://github.com/user-attachments/assets/fcf6f33c-e2d0-45c0-9f20-177cf6fa9dde)

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-04-24 14:07:29 +02:00
Andrii Chubatiuk
7390f99897 app/vmalert: fixed rule group ID in UI (#8803)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Co-authored-by: Roman Khavronenko <roman@victoriametrics.com>
Co-authored-by: Hui Wang <haley@victoriametrics.com>
2025-04-24 13:46:42 +02:00
Hui Wang
2d279750a9 lib/storage/downsampling: allow using -downsampling.period=filter:0s:0s to skip downsampling for time series that match the specified filter
* downsampling: allow using `-downsampling.period=filter:0s:0s` to skip downsampling for time series that match the specified `filter`

* doc minor fix

* lib/storage/downsampling: fix a typo in error message

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
Co-authored-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-04-24 14:41:37 +04:00
Artem Navoiev
e9c577132d docs: tag all documentation pages (#8793)
### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-24 02:58:02 -07:00
Yury Molodov
899d70a93e vmui: fix /flags API requests to respect custom URL prefixes (#8777)
### Describe Your Changes

Fixes incorrect /flags request in vmui when using URL prefixes.
 
 Related issue: #8641 

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-24 11:33:43 +02:00
Yury Molodov
1d13718fcf vmui/logs: fix oversized Query History button on mobile (#8794)
### Describe Your Changes

Fixes oversized `Query History` button on mobile in logs UI.
Related issue: #8788 

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-04-24 11:25:17 +02:00
Yury Molodov
fa4708178f vmui: hide duplicate legend items in Raw Query (#8784)
### Describe Your Changes

Hide identical series in the legend on the Raw Query page when
deduplication is disabled.

Related issue: #8688

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-24 11:20:41 +02:00
Harilou
e0ff58ce5e app/vmlogs: Replace elasticsearch plugin with opensearch plugin of logstash
### Describe your changes

1. When I used the opensearch plugin in the reference example, I found a
bug that caused memory exhaustion and stopped working. There is a
similar issue in the opensearch community:
https://github.com/opensearch-project/logstash-output-opensearch/issues/186,
@chadmyers raised this issue, but it has not been fixed yet. It has been
verified that the elasticsearch plugin does not have this problem.

![image](https://github.com/user-attachments/assets/cc2cbbfc-6dde-43af-8aca-3c1e371e1890)


2. In the vmlogs logstash docking example, it is consistent with the
official document's example of using the elasticsearch plugin.
https://docs.victoriametrics.com/victorialogs/data-ingestion/logstash/

### Checklist

The following checks are **required**:

- [x] My changes follow the [VictoriaMetrics Contribution
Guide](https://docs.victoriametrics.com/contributing/).
2025-04-24 12:07:56 +04:00
Yury Molodov
a9f03605d3 vmui/logs: handle ANSI escape sequences (#8548)
### Describe Your Changes

1. Added a toggle to enable parsing of ANSI escape sequences (e.g.,
color codes).
    Related issue:  #6614
2. Fixed the display of raw fields when the `_msg` field is missing. 
    Related issue: #8205
3. Fixed log display in Group view when Markdown parsing is enabled. 
    Related issue: #8575
4. Moved the Markdown parsing toggle to **Group View Settings**.
5. Configured testing setup.

<details>
<summary>Demo UI:</summary>

<br/>

**Disabled ANSI parsing:**

![image](https://github.com/user-attachments/assets/7f466051-ea6c-4ff7-b386-a3df4bb503c9)

**Enabled ANSI parsing:**

![image](https://github.com/user-attachments/assets/04074b6e-b1c2-4d5e-a8c2-5f58ca88494b)


</details>


### Checklist

The following checks are **mandatory**:

- [ ] My change adheres [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-23 15:25:07 +02:00
hagen1778
19025d5a19 docs: update metric names tracker
* update wording;
* add more details about returned response;
* cover details on counter increments;

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-23 15:02:57 +02:00
hagen1778
1f8c115428 docs: move metric usage doc closer to similar APIs
Before, this doc section was related to vmui, by mistake.
Moved it closer to tsdb stats, where it makes more sense to be.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-23 14:37:02 +02:00
hagen1778
1863c5b95b docs: remove badges from the main page
Badges is more a decorative element rather than source of useful information.
Some badges break from time to time, giving misleading impression to users.
It is better to remove them to reduce visual load and confusion.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-23 14:35:03 +02:00
Hui Wang
7756046865 vmalert: correctly update the debug param for recording rule when u… (#8792)
…pdating the rule group

Refactor the `TestUpdateWith` a bit in preparation for
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8658
2025-04-23 14:32:07 +02:00
Zakhar Bessarab
7f2d194948 lib/backup/s3remote: enable HTTP/2 for S3 connections
### Describe Your Changes

HTTP/2 support is used by some S3-compatible storage providers, so
disabling it default leads to unexpected errors when trying to connect
to S3 endpoint.
For example, using MinIO as S3 storage backend: `net/http: HTTP/1.x
transport connection broken: malformed HTTP response`.

HTTP/2 was enabled by default previously, but while fixing inconsistency
e5f4826 commit disabled this by default.
cc: @valyala 

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-04-23 09:45:07 +04:00
Zakhar Bessarab
f224b60410 fix: compatibility for FIPS builds
### Describe Your Changes

Fixes which are required in order to build FIPS-compliant binaries.
These changes were originally added for enterprise version and synced to
opensource for consistency and easier maintenance.

- consistently use `hash/fnv` at `app/vmalert` when calculating
checksums. Usage of md5 is not allowed in FIPS mode.
- increase encryption keys size used in testing in order to allow tests
to successfully run in FIPS mode

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
2025-04-23 09:43:07 +04:00
Aliaksandr Valialkin
46d32af89a lib/logstorage: add sample N for returning a random 1/Nth sample of matching logs 2025-04-22 16:37:07 +02:00
Aliaksandr Valialkin
3a7ea02d41 deployment: update VictoriaLogs Docker image from v1.19.0-victorialogs to v1.20.0-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.20.0-victorialogs
2025-04-22 14:30:17 +02:00
Aliaksandr Valialkin
84d2922f5e all: consistently use Grafana dashboard links ending with dashboard ID
The suffix after the ID may change in dashboard settings.
If it changes, the link becomes broken (dubious decision at grafana.com/grafana/dashboards/ ).
That's why it is better to drop all the suffixes and use links for Grafana dashbooards ending with IDs.
In this case they are automatically redirected to the url with the proper suffix.

This is a follow-up for 3e4c38c56c

See also the previous commits 9c0863babc and 0a5ffb3bc1
2025-04-22 14:20:15 +02:00
hagen1778
39b27cb397 docs: fix typo
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-22 14:13:01 +02:00
Zakhar Bessarab
b1523f650d lib/promrelabel/debug: use stricter format for labels (#8770)
### Describe Your Changes

Previously, it was possible to use any UTF-8 string to specify list of
labels. While this makes it easier to use it also leads to unexpected
parsing results in some cases (see
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8584 as an
example).

Enforce specifying metric in format {label="value"...} in order to avoid
issues with unexpected parsing results.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: Zakhar Bessarab <z.bessarab@victoriametrics.com>
Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-04-22 14:10:25 +02:00
Aliaksandr Valialkin
297bc28e3d docs/victorialogs/CHANGELOG.md: cut v1.20.0-victorialogs 2025-04-22 13:53:58 +02:00
Aliaksandr Valialkin
54bb834c16 app/vlselect/vmui: run make vmui-logs-update after faf95b4a58 2025-04-22 13:53:40 +02:00
Aliaksandr Valialkin
edee80f215 docs/victorialogs/CHANGELOG.md: move the description of the bugfix for https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8647 into the appropriate place
The bugfix for https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8647 isn't released yet,
so it must be placed under the `tip` section.

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8648
2025-04-22 13:49:19 +02:00
Aliaksandr Valialkin
5491d54c11 lib/logstorage: buffer the ingested log entries before converting them into searchable parts
This reduces the overhead needed for converting the ingested log entries to searchable in-memory parts
when small number of log entries are passed to Storage.MustAddRows().

The BenchmarkStorageMustAddRows shows up to 10x performance increase for rowsPerInsert=1,
up to 5x performance increase for rowsPerInsert=10 and up to 2x performance increase for rowsPerInsert=100.

This should reduce CPU usage during data ingestion when every request contains small number of rows.
2025-04-22 13:49:17 +02:00
Aliaksandr Valialkin
14561a7ed3 lib/logstorage: add a benchmark for different number of rows added to the storage via Storage.MustAddRows() 2025-04-22 13:49:15 +02:00
Artem Navoiev
cd4ec0e739 dashboards: update statistic by tenant dashboard add instant churn ra… (#8779)
…te panel

### Describe Your Changes

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-04-22 13:46:46 +02:00
hagen1778
8e76b41081 docs: fix broken links after docker-compose updates
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-22 13:39:33 +02:00
f41gh7
9751ea1098 fixes tests after 795d3fe722
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-04-22 11:59:22 +03:00
Roman Khavronenko
787e6a9b24 app/vmalert/remotewrite: rm noisy shutdown logs
On shutdown, rw client printed two log messages about shutting down and
how many series it flushed on shut down.

This commit removes these log messages for the following reasons:
1. These messages were printed for each `client.cc`, which is set to x2
of available CPUs. This behavior generated a lot of useless logs on
shutdown.
2. Number of flushed series on shutdown doesn't matter to the user.

Instead, it now prints only two log messages: when shutdown starts and
when it ends:
```
^C2025-04-22T07:37:11.932Z      info    VictoriaMetrics/app/vmalert/main.go:189 service received signal interrupt
2025-04-22T07:37:11.932Z        info    VictoriaMetrics/app/vmalert/remotewrite/client.go:152   shutting down remote write client: flushing remained series
2025-04-22T07:37:11.933Z        info    VictoriaMetrics/app/vmalert/remotewrite/client.go:155   shutting down remote write client: finished in 210.917µs
```

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-22 11:50:23 +03:00
f41gh7
73a69bd655 app/vmselect/netstorage: properly set max read size for metric name
Previously, metric names stats API had a false assumption, that max
size of metric name is 256 byte. But this is configurable parameter with
4096 bytes max size. It triggered errors during API requests.

 This commit replaces hard-coded 256 byte limit with common constant:
maxLabelValueSize. It has 16 MB limit.

 In addition, this commit adds check for metric name stats tracker,
if metric name size exceeds default buffer limit, it will be allocated
directly on heap. It must be rare case, since most metric names has
16-64 byte size.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8759
2025-04-22 11:36:16 +03:00
f41gh7
ec6ed3cb48 lib/storage/metricnamestats: allow regex for match_pattern
This commit allows regex syntax for match_pattern query param.
It improves API usability.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6145
2025-04-22 11:35:23 +03:00
Yury Molodov
faf95b4a58 vmui/logs: update button styles to improve hover performance
Refactors button styles to fix high CPU usage on hover in the logs UI.

 Related issue: #
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8135
2025-04-22 11:28:19 +03:00
Artur Minchukou
a7106040de app/vmui/logs: add 0 label to the Y axis
Added 0 label to the Y axis on VictoriaLogs chart.


Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8409
2025-04-22 11:26:34 +03:00
Phuong Le
792d0f8bb8 vmagent: reduce log noise from remote write retries
Throttle remote write retry warning logs to one message per 5 seconds.
This reduces log noise during connectivity issues.

Users can monitor `vmagent_remotewrite_retries_count_total` and
`vmagent_remotewrite_errors_total` metrics for detailed retry rates per
destination if needed. This change prioritizes reducing log volume over
immediate destination-specific error logging in the retry warnings.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8723
2025-04-22 11:20:33 +03:00
Phuong Le
8628f90e6b lib/storage: put the unused in-memory part back into the pool 2025-04-22 11:19:50 +03:00
Georgy Torquemada
89237a04b9 fix: add missed severity levels (warn) for protobuff parser
Closes
[8647](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8647)

### Describe Your Changes

Added missed OTEL severities levels, added test for severity, fix some
severity in given tests

### Checklist

The following checks are **mandatory**:

- [x] My change adheres [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-21 16:39:10 +04:00
Aliaksandr Valialkin
d6c156727b docs: remove misleading requirements for the minimum supported Go version needed for building VictoriaMetrics executables
VictoriaMetrics executables need the latest available stable release of Go (1.24 currently),
since they use its features. See, for example, GOEXPERIMENT=synctest from the commit 06c26315df .

There is no need in specifying the minimum supported Go version for building VictoriaMetrics products,
since Go automatically downloads and uses the version specified at `go ...` directive inside go.mod
starting from Go1.21. See https://go.dev/doc/toolchain for details.

So the actual minimum needed Go version is Go1.21, which has been released 1.5 years ago. It should automatically
install newer Go versions specified at `go ...` directive inside go.mod.
2025-04-21 13:06:09 +02:00
Aliaksandr Valialkin
f1fdc8610d lib/promscrape: prevent from excess memory allocation during scrapes when sample_limit is exceeded
Do not reset wc.labels in order to properly keep track of the number of used labels for the scrape,
and properly re-use the same number of wc.labels on subsequent scrapes.

See 12f26668a6 (r155481168)
2025-04-21 13:06:08 +02:00
Artem Navoiev
611450a188 docs: kuma sd actualize link
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-19 20:37:44 +02:00
Artem Navoiev
3b1a41c014 docs: victorialogs fix link to external collectiors
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-19 10:53:17 +02:00
hagen1778
cd9bb6b315 docs: rm links to swiftstack
Swiftstack s3 service and docs seems unavailable anymore.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-19 07:35:27 +02:00
Artem Navoiev
e58d3f03c7 docs: victoriametrics home page use relative anchor
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-18 22:22:44 +02:00
Artem Navoiev
3e4c38c56c docs: changelog fix link to grafana dashboard as far we rename it. Point to 2.53 (LTS) release of prometheus in vmalert as far link to 2.49 doesn't exist anymore
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-18 22:21:00 +02:00
Artem Navoiev
c3becae96b docs: actualize link to timescale compression in faq
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-18 22:12:33 +02:00
Artem Navoiev
84ee713dc6 docs: home victoriametrics fix link to readme.md file
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-18 22:06:01 +02:00
Artem Navoiev
7dc58894d1 docs: changelog remove deadlink to mesosphere marathon as far project in achive since october 2024 see https://github.com/d2iq-archive/marathon
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-18 21:55:47 +02:00
Artem Navoiev
30376722c1 docs: fix wrong link in cluster documentation, point to the new era5 page in data examples
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-18 21:44:11 +02:00
Artem Navoiev
6674691a58 docs: victoriametrics list current urls for redict to simplify the feature changes. More urls
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-18 21:10:46 +02:00
Artem Navoiev
55e3ccb5f0 docs: victoriametrics list current urls for redict to simplify the feature changes
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-18 20:44:01 +02:00
hagen1778
2c97c8841c deployment/docker: fix routing for vlogs vmui
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-18 13:55:25 +02:00
Andrii Chubatiuk
f38736343d deployment/docker: added victorialogs cluster docker compose setup (#8725)
### Describe Your Changes

fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8694

additionally removed container_name, docker network, renamed all
compose, config files for consistency

Please provide a brief description of the changes you made. Be as
specific as possible to help others understand the purpose and impact of
your modifications.

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-04-18 13:47:53 +02:00
Aliaksandr Valialkin
33315f1ece deployment/docker: update VictoriaLogs from v1.18.0-victorialogs to v1.19.0-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.19.0-victorialogs
2025-04-17 20:25:47 +02:00
Aliaksandr Valialkin
680cbef0cb docs/victorialogs/CHANGELOG.md: cut v1.19.0-victorialogs release 2025-04-17 20:15:20 +02:00
Aliaksandr Valialkin
2d3e048f59 docs/victorialogs/CHANGELOG.md: mention @arturminchukov as the author of the recent Web UI changes 2025-04-17 20:13:18 +02:00
Aliaksandr Valialkin
024a40a799 app/{vmselect,vlselect} run make vmui-update vmui-logs-update after 5fa40ee631 2025-04-17 20:08:28 +02:00
Aliaksandr Valialkin
225c6b6f52 docs/victorialogs/CHANGELOG.md: clarify the description of the bugfix in the commit 0fee22e91a
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8743
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8707
2025-04-17 20:05:39 +02:00
Andrii Chubatiuk
0fee22e91a lib/logstorage: expect message in a field with empty and _msg name (#8743)
### Describe Your Changes

fixes #8707

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
2025-04-17 19:55:37 +02:00
Max Kotliar
96200a9ec4 vmagent: use tmp dir in integrations tests (#8748)
Before the change, the vmagent integration tests created their directory
and files inside apptest/tests.
After the change, vmagent is instructed to store all files in a real
temporary directory, which is automatically deleted after the tests
complete.
2025-04-17 18:23:42 +02:00
Artem Fetishev
06c26315df lib/storage: test wasMetricIDsMissingBefore with "testing/synctest" (#8740)
Using this package lets to manipulate time. In this particular case, it
lets to advance the time 61 second forward instantly.

A few side changes were necessary:

- Do not use fasttime in unit tests. The fasttime package starts a
goroutine outside the test bubble which causes the clock to be real, not
fake.
- Stop the time.Ticker explicitly and also stop idbNext. These two
create goroutines with infinite loops which causes the unit tests that
use synctest to hang forever. All goroutines created inside the bubble
must exit in order for the syntest to finish.
- synctest is an experimental package and requires an environment
variable to be set. The Makefile was changed to set it.

Signed-off-by: Artem Fetishev <rtm@victoriametrics.com>
2025-04-17 16:58:47 +02:00
Max Kotliar
231810fe49 lib/protoparser/protoparserutil: restore write concurrency limiter in ReadUncompressedData due to performance regressions (#8742)
### Describe Your Changes

The write concurrency limiter in ReadUncompressedData was previously
removed in

22d1b916bf
to avoid suboptimal behavior in certain scenarios. However, follow-up
reports—including issue
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8674 and
production feedback from VictoriaMetrics Cloud—indicated a noticeable
degradation in performance after its removal.

To mitigate these regressions, this commit reintroduces the concurrency
limiter. A long-term, more optimal solution will be explored separately
in issue https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8728.

TODO:

* [x] Changelog


### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-04-17 14:05:41 +02:00
hagen1778
60ef715c79 docs: fix newline typo in query-stats.md
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-17 12:25:59 +02:00
hagen1778
8071dabe58 docs: update query-stats.md
* fix typos
* improve wording
* link grafana dashboard

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-17 12:23:15 +02:00
hagen1778
3d9b160fce docs: make query-stats.md available in docs
The doc was incorrectly ported into wrong directory after
a113516588
This change moves it to the victoriametrics dir.

While there, updated the order of some pages to couple them by meaning.

Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-17 12:15:17 +02:00
Yury Molodov
5fa40ee631 vmui/logs: fix incorrect table sorting for numeric (#8646)
### Describe Your Changes

Fixed table sorting logic and added unit tests for descendingComparator.
Values are now correctly sorted by type: number, date, or string.

Related issue: #8606

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-04-17 09:40:46 +02:00
Artur Minchukou
53814b1ea6 app/vmui: add query history to VictoriaLogs (#8703)
### Describe Your Changes
Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8500

Added query history to VictoriaLogs

### Checklist

The following checks are **mandatory**:

- [ ] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-04-17 09:34:15 +02:00
Artur Minchukou
9ca2a246a9 app/vmui: fix mobile layout on the VictoriaLogs page, fix width of groups and table settings modal (#8679)
### Describe Your Changes
 - Fix mobile layout on the VictoriaLogs page
<img width="361" alt="image"
src="https://github.com/user-attachments/assets/2e09b999-34d5-4059-ba09-95a21b3e8ab3"
/>
<img width="353" alt="image"
src="https://github.com/user-attachments/assets/b9048d41-5972-4290-988f-e9b0a0472b99"
/>
 
- Fix width of groups settings modal
<img width="372" alt="image"
src="https://github.com/user-attachments/assets/e1cb1902-dc93-4bfd-8b32-eaf0d8e54253"
/>
<img width="352" alt="image"
src="https://github.com/user-attachments/assets/a7c7000f-2c4a-41d9-a3c1-a515fd077b9b"
/>

- Fix width of table settings modal
<img width="361" alt="image"
src="https://github.com/user-attachments/assets/12921936-6824-47e9-aff8-d0bb4de2e7f7"
/>
<img width="352" alt="image"
src="https://github.com/user-attachments/assets/77c857ee-85f4-4992-8113-4e252b40f1a6"
/>

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-04-17 09:27:10 +02:00
Artur Minchukou
4517425da8 app/vmui: add export logs button to VictoriaLogs (#8671)
### Describe Your Changes
Related issue:
[#8604](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8604)

Added a download logs button to VictoriaLogs, which allows you to export
logs in the following formats: csv, json.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Signed-off-by: hagen1778 <roman@victoriametrics.com>
Co-authored-by: hagen1778 <roman@victoriametrics.com>
2025-04-17 09:14:41 +02:00
Yury Molodov
953ed46680 vmui: update package.json
### Describe Your Changes

Bumped project dependencies in `package.json` to the latest stable
versions.
2025-04-16 20:19:17 +02:00
f41gh7
795d3fe722 lib/storage: enhance TSDB status response
This commit adds new fields - `requestsCount` and `lastRequestTimestamp`
to series count be metric names stats.
It allows to display an additional stats at explore cardinality page.
Stats will only be added if `storage.trackMetricNameStats` flag is set.

 This change requires an update to RPC protocol in order to properly
marshal data.

 In addition, this commit adds integration tests to TSDB stats API.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6145
2025-04-16 20:09:35 +02:00
f41gh7
536b40c06c make linter happy after a113516588 2025-04-16 19:55:54 +02:00
Roman Khavronenko
a113516588 app/vmselect: log search query request stats
This commit adds `search.logSlowQueryStats=<duration>` cmd-line flag on vmselect.
It reads stats from eval function, and doesn't slow down the query execution.

 Log line has the following structure:

 vm_slow_query_stats type=%s query=%q query_hash=%d start_ms=%d end_ms=%d step_ms=%d range_ms=%d tenant=%q execution_duration_ms=%v series_fetched=%d samples_fetched=%d bytes=%d memory_estimated_bytes=%d

 This feature is only available for enterprise version.
2025-04-16 19:39:13 +02:00
Fred Navruzov
b68f9ea9e3 docs/vmanomaly - release 1.22.0 - experimental (#8717)
### Describe Your Changes

Changelog note about experimental v1.22.0 release that solves deadlock
issue on multicore systems by complete parallelization turned off until
proper refactor is made to return it back w/o reintroducing the risk of
the deadlock in child processes.

P.s. other references and guides were not updated to experimental tag,
as long as it has downsides of dropped speed. The links will be updated
once we have parallelization properly turned on.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-14 15:56:10 +03:00
Roman Khavronenko
fa6a32a39d ci: temporary disable vlogs tests for i386
This change unblocks testing pipelines in CI for other contributions.
The tests are commented because I don't have full understanding of
fixing them.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8710

---------
Signed-off-by: hagen1778 <roman@victoriametrics.com>
2025-04-14 11:11:43 +02:00
Max Kotliar
477635e00f Follow up to "vmagent/client: Use VictoriaMetrics remote write protocol by default, downgrade to Prometheus if needed" (#8706)
### Describe Your Changes

Follow-up to
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8462

Addressed review comments:
- Log panic with FATAL prefix to indicate possible on-disk data
corruption
- Moved version bump line to the tip block (v1.114.0 has already been
released) in changelog
- Removed duplicate vmagent entry from targets list from Makefile


### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).

---------

Co-authored-by: Roman Khavronenko <roman@victoriametrics.com>
2025-04-14 11:55:01 +03:00
Max Kotliar
8e92cd3b2d lib/writeconcurrencylimiter: add some hints to unexpected EOF error message. (#8704)
### Describe Your Changes

Under heavy load, vmagent's wirte concurrency limiter

(2ab53acce4/lib/writeconcurrencylimiter/concurrencylimiter.go (L111))
queues incoming requests. If a client's timeout is shorter than the wait
time in the
queue, the client may close the connection before vmagent starts
processing it. When vmagent then tries to read the request body, it
encounters an ambiguous `unexpected EOF` error
(https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8675).

This commit adds more context to such errors to help users diagnose and
resolve
the issue when it's related to vmagent's own load and queuing behavior.

Possible user actions include:
- Lowering `-insert.maxQueueDuration` below the client's timeout.
- Increasing the client-side timeout, if applicable.
- Scaling up vmagent (e.g., adding more CPU resources).
- Increasing `-maxConcurrentInserts` if CPU capacity allows.

Steps to reproduce:
https://gist.github.com/makasim/6984e20f57bfd944411f56a7ebe5b6bf

### Checklist

The following checks are **mandatory**:

- [x] My change adheres to [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-13 11:22:12 +03:00
Max Kotliar
2ab53acce4 vmagent/client: Use VictoriaMetrics remote write protocol by default, downgrade to Prometheus if needed (#8462)
### Describe Your Changes

This commit improves how vmagent selects the remote write protocol.
Previously, vmagent [performed a handshake
probe](0ff1a3b154/lib/protoparser/protoparserutil/vmproto_handshake.go (L11))
at
[startup](0ff1a3b154/app/vmagent/remotewrite/client.go (L173)):

- If the probe succeeded, it used the VictoriaMetrics (VM) protocol.

- If the probe failed, it downgraded to the Prometheus protocol.

- No protocol changes occurred after the initial probe at runtime.

However, this approach had limitations:

- If vmstorage was unavailable during vmagent startup, vmagent would
immediately downgrade to the Prometheus protocol, leading to higher
network usage unitl vmagent restarted. This case has been reported in
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7615.

- If the remote write server was updated or downgraded (e.g., during a
fallback or migration), vmagent would not detect the protocol change. It
would continue retrying failed requests and eventually drop them.
Require a restart of vmagent to pick up the new protocol.

This commit introduces a more adaptive mechanism.
vmagent always starts with the VM protocol and downgrades to the
Prometheus protocol only if an unsupported media type or bad request
response is received.
When this happens, the protocol is downgraded for all future requests.
In-flight requests are re-packed from Zstd to Snappy and retried
immediately.
Snappy-encoded requests are dropped if an unsupported media type or bad
request is received (no retrying).

Additionally, the in-memory and persisted queues could mix snappy and
zstd encoded blocks. The proper encoding is decided before sending by
encoding.IsZstd function.

TODO:
* [x] Add tests
* [x] Update documentation
* [x] Changelog
* [x] Research on
[content-type](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8462#issuecomment-2786918054),
[accept-encoding](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8462#issuecomment-2786923382)

Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7615#top
issue.

### Checklist

The following checks are **mandatory**:

- [x] My change adheres [VictoriaMetrics contributing
guidelines](https://docs.victoriametrics.com/contributing/).
2025-04-12 10:39:47 +03:00
Aliaksandr Valialkin
2f4680d8f3 docs/victoriametrics/Articles.md: add a link to https://chronicles.mad-scientist.club/tales/grepping-logs-remains-terrible/ 2025-04-10 23:10:24 +02:00
Aliaksandr Valialkin
1f1afeb06e lib/logstorage: add support for <duration_seconds:field> formatting option for format pipe
This option formats duration values as floating-point seconds.
2025-04-10 22:55:08 +02:00
Aliaksandr Valialkin
b2c075191e docs/victorialogs/cluster.md: add an example on how to query every vmstorage node as a single-node VictoriaLogs 2025-04-10 22:16:31 +02:00
f41gh7
1191c6453b app/vmagent: properly init kafka consumer
Previously, if vmagent was built with CGO_ENABLED=0, vmagent cannot start and reported runtime error:

 `Kafka client is not supported at systems without CGO`

 This error was trigger even if `-kafka.consumer.topic` was not
 provided. CGO_ENABLED=0 is default build option for linux/arm and some other archs.

 This commit properly inits kafka consumer by checking if `-kafka.consumer.topic` is set.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6019
2025-04-10 18:15:36 +02:00
Aliaksandr Valialkin
5d61122fd5 docs/victorialogs/cluster.md: add a link to the changelog for the latest available release 2025-04-10 17:09:23 +02:00
Aliaksandr Valialkin
e9c04879ce docs/victorialogs/CHANGELOG.md: add release date for v1.18.0-victorialogs 2025-04-10 17:07:58 +02:00
Aliaksandr Valialkin
5f4205a050 deployment: update VictoriaLogs Docker image tag from v1.17.0-victorialogs to v1.18.0-victorialogs
See https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.18.0-victorialogs
2025-04-10 17:04:30 +02:00
Aliaksandr Valialkin
7a46af3920 victorialogs: add cluster mode
Cluster mode is enabled when -storageNode command-line flag is passed to VictoriaLogs.
In this mode it spreads the ingested logs among storage nodes specified in the -storageNode flag.
It also queries storage nodes during `select` queries.

Cluster mode allows building multi-level cluster setup when top-level select node can query multiple lower-level clusters
and get global querying view.

See https://docs.victoriametrics.com/victorialogs/cluster/

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5077
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7950
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8223
2025-04-10 16:55:23 +02:00
Aliaksandr Valialkin
ff967a8e65 lib/protoparser: support for identity encoding in a generic way inside protoparserutil.GetUncompressedReader
This should help avoiding future issues when `identity` encoding isn't replaced to `` encoding
by the caller of protoparserutil.GetUncompressedReader().

This is a follow-up for 303b425fa3

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8652
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8649
2025-04-10 13:52:45 +02:00
Artem Navoiev
3108376d95 docs: changelog fix the link to cluster version in 114 release.2
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-10 09:39:15 +02:00
Artem Navoiev
494fe4403a docs: changelog fix the link to cluster version in 114 release
Signed-off-by: Artem Navoiev <tenmozes@gmail.com>
2025-04-09 21:28:40 +02:00
Andrii Chubatiuk
303b425fa3 lib/protoparser/datadog*: support Content-Encoding: identity value
introduction of common decompression logic in
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8416 removed
ability to treat unsupported compression algorithms as uncompressed data
for datadog v1 endpoint. This PR adds support of `identity`
Content-Encoding header value, though according to RFC 2616 this value
is only expected in `Accept-Encoding` header

related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8649
2025-04-08 16:17:19 +02:00
Nikolay
8f3efde55d lib/httpserver: mask authKey at PostFrom
'authKey' is well-known url and form param for VictoriaMetrics
components authorization. Previously, it could be printed into stdout
via httpserver error logger. It makes this authKey insecure and hard to
use.

This commit prevents from logging authKey defined at PostForm or as part
of url.Query.

It's recommneded to transfer authKey via PostForm and it should be
implemented at separate PRs.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5973

---------
Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-04-08 16:15:48 +02:00
Nikolay
f16938bba9 lib/backup/s3: properly set ProfileName
Previously, if ProfileName is set to empty value (as default). AWS s3
lib ignored any profile config defined with `-configProfilePath`.

This commit correctly configure client options and set profile name only
if it's set to non-empty value.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8668
2025-04-08 16:15:07 +02:00
nemobis
65ff04bc09 docs: Fix typo in changelog for v113
Fix a typo `scrapped` for `scraped`.
2025-04-08 16:14:50 +02:00
Zakhar Bessarab
e2715f94af docs/guides/vmgateway-grafana-oidc: update guide for recent versions of components
- update grafana & keycloak to latest versions
- update UI images with the latest screenshots
- update wording to reflect UI changes
2025-04-08 16:13:58 +02:00
Zakhar Bessarab
582160f566 make: fix make package for vmalert-tool
`make package` relies on presence of `APP_NAME/deployment/Dockerfile`
which was missing for vmalert-tool.
2025-04-08 16:13:28 +02:00
nemobis
638f9839d5 docs: fix typo in pull request template
The verb is _adhere to_, see https://en.wiktionary.org/wiki/adhere .
2025-04-08 16:12:51 +02:00
Max Kotliar
3f5bf4bd03 vmagent/remotewrite: set content encoding header based on actual body
Improve remote write handling in vmagent by setting the
`Content-Encoding` header based on the actual request body, rather than
relying on configuration.

- Detects Zstd compression via the Zstd magic number.
- Falls back to Snappy if Zstd is not detected.
- Persistent queue may now contain mixed-encoding content.
- Add basic vmagent integration tests

Follow up on
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/5344 and
12cd32fd75.

Extracted from
https://github.com/VictoriaMetrics/VictoriaMetrics/pull/8462

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5301
2025-04-08 16:12:06 +02:00
f41gh7
038419663b docs: release follow-up
* mention lts release changes
* update vm apps versions at docs and deployment examples

Signed-off-by: f41gh7 <nik@victoriametrics.com>
2025-04-07 12:59:53 +02:00
3522 changed files with 548227 additions and 255532 deletions

View File

@@ -5,10 +5,10 @@ body:
- type: markdown
attributes:
value: |
Before filling a bug report it would be great to [upgrade](https://docs.victoriametrics.com/#how-to-upgrade)
Before filling a bug report it would be great to [upgrade](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#how-to-upgrade)
to [the latest available release](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest)
and verify whether the bug is reproducible there.
It's also recommended to read the [troubleshooting docs](https://docs.victoriametrics.com/troubleshooting/) first.
It's also recommended to read the [troubleshooting docs](https://docs.victoriametrics.com/victoriametrics/troubleshooting/) first.
- type: textarea
id: describe-the-bug
attributes:
@@ -64,8 +64,8 @@ body:
* [Grafana dashboard for VictoriaMetrics cluster](https://grafana.com/grafana/dashboards/11176)
See how to setup monitoring here:
* [monitoring for single-node VictoriaMetrics](https://docs.victoriametrics.com/#monitoring)
* [monitoring for VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/#monitoring)
* [monitoring for single-node VictoriaMetrics](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#monitoring)
* [monitoring for VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/#monitoring)
validations:
required: false
- type: textarea

View File

@@ -24,9 +24,9 @@ body:
label: Troubleshooting docs
description: I am familiar with the following troubleshooting docs
options:
- label: General - https://docs.victoriametrics.com/troubleshooting/
- label: General - https://docs.victoriametrics.com/victoriametrics/troubleshooting/
required: false
- label: vmagent - https://docs.victoriametrics.com/vmagent/#troubleshooting
- label: vmagent - https://docs.victoriametrics.com/victoriametrics/vmagent/#troubleshooting
required: false
- label: vmalert - https://docs.victoriametrics.com/vmalert/#troubleshooting
- label: vmalert - https://docs.victoriametrics.com/victoriametrics/vmalert/#troubleshooting
required: false

23
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,23 @@
# Project Overview
VictoriaMetrics is a fast, cost-saving, and scalable solution for monitoring and managing time series data. It delivers high performance and reliability, making it an ideal choice for businesses of all sizes.
## Folder Structure
- `/app`: Contains the compilable binaries.
- `/lib`: Contains the golang reusable libraries
- `/docs/victoriametrics`: Contains documentation for the project.
- `/apptest/tests`: Contains integration tests.
## Libraries and Frameworks
- Backend: Golang, no framework. Use third-party libraries sparingly.
- Frontend: React.
## Code review guidelines
Ensure the feature or bugfix includes a changelog entry in /docs/victoriametrics/changelog/CHANGELOG.md.
Verify the entry is under the ## tip section and matches the structure and style of existing entries.
Chore-only changes may be omitted from the changelog.

View File

@@ -6,4 +6,5 @@ Please provide a brief description of the changes you made. Be as specific as po
The following checks are **mandatory**:
- [ ] My change adheres [VictoriaMetrics contributing guidelines](https://docs.victoriametrics.com/contributing/).
- [ ] My change adheres to [VictoriaMetrics contributing guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist).
- [ ] My change adheres to [VictoriaMetrics development goals](https://docs.victoriametrics.com/victoriametrics/goals/).

View File

@@ -7,16 +7,20 @@ on:
- master
paths:
- '**.go'
- '**/Dockerfile*' # The trailing * is for app/vmui/Dockerfile-*.
- '**/Dockerfile'
- '**/Makefile'
- '!app/vmui/**'
- '.github/workflows/build.yml'
pull_request:
branches:
- cluster
- master
paths:
- '**.go'
- '**/Dockerfile*' # The trailing * is for app/vmui/Dockerfile-*.
- '**/Dockerfile'
- '**/Makefile'
- '!app/vmui/**'
- '.github/workflows/build.yml'
permissions:
contents: read
@@ -27,28 +31,48 @@ concurrency:
jobs:
build:
name: Build
name: ${{ matrix.os }}-${{ matrix.arch }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- os: linux
arch: 386
- os: linux
arch: amd64
- os: linux
arch: arm64
- os: linux
arch: arm
- os: linux
arch: ppc64le
- os: darwin
arch: amd64
- os: darwin
arch: arm64
- os: freebsd
arch: amd64
- os: openbsd
arch: amd64
- os: windows
arch: amd64
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Setup Go
id: go
uses: actions/setup-go@v5
with:
cache-dependency-path: |
go.sum
Makefile
app/**/Makefile
go-version: stable
cache: false
- name: Cache Go artifacts
uses: actions/cache@v4
with:
path: |
~/.cache/go-build
~/go/bin
~/go/pkg/mod
key: go-artifacts-${{ runner.os }}-crossbuild-${{ steps.go.outputs.go-version }}-${{ hashFiles('go.sum', 'Makefile', 'app/**/Makefile') }}
restore-keys: go-artifacts-${{ runner.os }}-crossbuild-
- name: Build victoria-metrics for ${{ matrix.os }}-${{ matrix.arch }}
run: make victoria-metrics-${{ matrix.os }}-${{ matrix.arch }}
- name: Run crossbuild
run: make crossbuild
- name: Build vmutils for ${{ matrix.os }}-${{ matrix.arch }}
run: make vmutils-${{ matrix.os }}-${{ matrix.arch }}

View File

@@ -29,7 +29,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Set up Go
id: go

View File

@@ -1,46 +0,0 @@
name: 'CodeQL JS/TS'
on:
push:
branches:
- cluster
- master
paths:
- '**.js'
- '**.ts'
- '**.tsx'
pull_request:
branches:
- cluster
- master
paths:
- '**.js'
- '**.ts'
- '**.tsx'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript-typescript
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: 'language:js/ts'

View File

@@ -16,12 +16,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
path: __vm
- name: Checkout private code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
repository: VictoriaMetrics/vmdocs
token: ${{ secrets.VM_BOT_GH_TOKEN }}

View File

@@ -1,122 +0,0 @@
name: main
on:
push:
branches:
- cluster
- master
paths:
- '**.go'
pull_request:
branches:
- cluster
- master
paths:
- '**.go'
permissions:
contents: read
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
jobs:
lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v4
- name: Setup Go
id: go
uses: actions/setup-go@v5
with:
cache: false
go-version: stable
- name: Cache Go artifacts
uses: actions/cache@v4
with:
path: |
~/.cache/go-build
~/go/bin
~/go/pkg/mod
key: go-artifacts-${{ runner.os }}-check-all-${{ steps.go.outputs.go-version }}-${{ hashFiles('go.sum', 'Makefile', 'app/**/Makefile') }}
restore-keys: go-artifacts-${{ runner.os }}-check-all-
- name: Run check-all
run: |
make check-all
git diff --exit-code
test:
name: test
needs: lint
runs-on: ubuntu-latest
strategy:
matrix:
scenario:
- 'test-full'
- 'test-full-386'
- 'test-pure'
steps:
- name: Code checkout
uses: actions/checkout@v4
- name: Setup Go
id: go
uses: actions/setup-go@v5
with:
cache: false
go-version: stable
- name: Cache Go artifacts
uses: actions/cache@v4
with:
path: |
~/.cache/go-build
~/go/bin
~/go/pkg/mod
key: go-artifacts-${{ runner.os }}-${{ matrix.scenario }}-${{ steps.go.outputs.go-version }}-${{ hashFiles('go.sum', 'Makefile', 'app/**/Makefile') }}
restore-keys: go-artifacts-${{ runner.os }}-${{ matrix.scenario }}-
- name: Run tests
run: GOGC=10 make ${{ matrix.scenario}}
- name: Publish coverage
uses: codecov/codecov-action@v5
with:
files: ./coverage.txt
integration-test:
name: integration-test
needs: [lint, test]
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v4
- name: Setup Go
id: go
uses: actions/setup-go@v5
with:
cache: false
go-version: stable
- name: Cache Go artifacts
uses: actions/cache@v4
with:
path: |
~/.cache/go-build
~/go/bin
~/go/pkg/mod
key: go-artifacts-${{ runner.os }}-${{ matrix.scenario }}-${{ steps.go.outputs.go-version }}-${{ hashFiles('go.sum', 'Makefile', 'app/**/Makefile') }}
restore-keys: go-artifacts-${{ runner.os }}-${{ matrix.scenario }}-
- name: Run integration tests
run: make integration-test

113
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,113 @@
name: test
on:
push:
branches:
- cluster
- master
paths:
- '**.go'
- 'go.*'
- '.github/workflows/main.yml'
pull_request:
branches:
- cluster
- master
paths:
- '**.go'
- 'go.*'
- '.github/workflows/main.yml'
permissions:
contents: read
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
jobs:
lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v5
- name: Setup Go
id: go
uses: actions/setup-go@v5
with:
cache-dependency-path: |
go.sum
Makefile
app/**/Makefile
go-version: stable
- name: Cache golangci-lint
uses: actions/cache@v4
with:
path: |
~/.cache/golangci-lint
~/go/bin
key: golangci-lint-${{ runner.os }}-${{ hashFiles('.golangci.yml') }}
- name: Run check-all
run: |
make check-all
git diff --exit-code
unit:
name: unit
runs-on: ubuntu-latest
strategy:
matrix:
scenario:
- 'test-full'
- 'test-full-386'
- 'test-pure'
steps:
- name: Code checkout
uses: actions/checkout@v5
- name: Setup Go
id: go
uses: actions/setup-go@v5
with:
cache-dependency-path: |
go.sum
Makefile
app/**/Makefile
go-version: stable
- name: Run tests
run: GOGC=10 make ${{ matrix.scenario}}
- name: Publish coverage
uses: codecov/codecov-action@v5
with:
files: ./coverage.txt
integration:
name: integration
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v5
- name: Setup Go
id: go
uses: actions/setup-go@v5
with:
cache-dependency-path: |
go.sum
Makefile
app/**/Makefile
go-version: stable
- name: Run integration tests
run: make integration-test

82
.github/workflows/vmui.yml vendored Normal file
View File

@@ -0,0 +1,82 @@
name: vmui
on:
push:
branches:
- cluster
- master
paths:
- 'app/vmui/packages/vmui/**'
- '.github/workflows/vmui.yml'
pull_request:
branches:
- cluster
- master
paths:
- 'app/vmui/packages/vmui/**'
- '.github/workflows/vmui.yml'
permissions:
contents: read
packages: read
pull-requests: read
checks: write
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
jobs:
vmui-checks:
name: VMUI Checks (lint, test, typecheck)
runs-on: ubuntu-latest
steps:
- name: Code checkout
uses: actions/checkout@v5
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '24.x'
- name: Cache node-modules
uses: actions/cache@v4
with:
path: |
app/vmui/packages/vmui/node_modules
key: vmui-artifacts-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: vmui-artifacts-${{ runner.os }}-
- name: Run lint
id: lint
run: make vmui-lint
continue-on-error: true
- name: Run tests
id: test
run: make vmui-test
continue-on-error: true
- name: Run typecheck
id: typecheck
run: make vmui-typecheck
continue-on-error: true
- name: Annotate Code Linting Results
uses: ataylorme/eslint-annotate-action@v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
report-json: app/vmui/packages/vmui/vmui-lint-report.json
- name: Check overall status
run: |
echo "Lint status: ${{ steps.lint.outcome }}"
echo "Test status: ${{ steps.test.outcome }}"
echo "Typecheck status: ${{ steps.typecheck.outcome }}"
if [[ "${{ steps.lint.outcome }}" == "failure" || "${{ steps.test.outcome }}" == "failure" || "${{ steps.typecheck.outcome }}" == "failure" ]]; then
echo "One or more checks failed"
exit 1
else
echo "All checks passed"
fi

2
.gitignore vendored
View File

@@ -12,6 +12,7 @@
/victoria-logs-data
/victoria-metrics-data
/vmagent-remotewrite-data
/vlagent-remotewritewrite
/vmstorage-data
/vmselect-cache
/package/temp-deb-*
@@ -27,3 +28,4 @@ _site
coverage.txt
cspell.json
*~
deployment/docker/provisioning/plugins/

View File

@@ -1,22 +1,29 @@
run:
timeout: 2m
version: "2"
linters:
enable:
- revive
issues:
exclude-rules:
- linters:
- staticcheck
text: "SA(4003|1019|5011):"
include:
- EXC0012
- EXC0014
linters-settings:
errcheck:
exclude-functions:
- "fmt.Fprintf"
- "fmt.Fprint"
- "(net/http.ResponseWriter).Write"
settings:
errcheck:
exclude-functions:
- fmt.Fprintf
- fmt.Fprint
- (net/http.ResponseWriter).Write
exclusions:
generated: lax
presets:
- common-false-positives
- legacy
- std-error-handling
rules:
- linters:
- staticcheck
text: 'SA(4003|1019|5011):'
paths:
- third_party$
- builtin$
- examples$
formatters:
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$

View File

@@ -1 +1 @@
The document has been moved [here](https://docs.victoriametrics.com/contributing/).
The document has been moved [here](https://docs.victoriametrics.com/victoriametrics/contributing/).

220
Makefile
View File

@@ -5,16 +5,20 @@ MAKE_PARALLEL := $(MAKE) -j $(MAKE_CONCURRENCY)
DATEINFO_TAG ?= $(shell date -u +'%Y%m%d-%H%M%S')
BUILDINFO_TAG ?= $(shell echo $$(git describe --long --all | tr '/' '-')$$( \
git diff-index --quiet HEAD -- || echo '-dirty-'$$(git diff-index -u HEAD | openssl sha1 | cut -d' ' -f2 | cut -c 1-8)))
LATEST_TAG ?= latest
PKG_TAG ?= $(shell git tag -l --points-at HEAD)
ifeq ($(PKG_TAG),)
PKG_TAG := $(BUILDINFO_TAG)
endif
EXTRA_DOCKER_TAG_SUFFIX ?=
EXTRA_GO_BUILD_TAGS ?=
GO_BUILDINFO = -X '$(PKG_PREFIX)/lib/buildinfo.Version=$(APP_NAME)-$(DATEINFO_TAG)-$(BUILDINFO_TAG)'
TAR_OWNERSHIP ?= --owner=1000 --group=1000
GOLANGCI_LINT_VERSION := 2.4.0
.PHONY: $(MAKECMDGOALS)
include app/*/Makefile
@@ -23,11 +27,10 @@ include docs/Makefile
include deployment/*/Makefile
include dashboards/Makefile
include package/release/Makefile
include benchmarks/Makefile
all: \
victoria-metrics-prod \
victoria-logs-prod \
vlogscli-prod \
vmagent-prod \
vmalert-prod \
vmalert-tool-prod \
@@ -51,8 +54,6 @@ publish: \
package: \
package-victoria-metrics \
package-victoria-logs \
package-vlogscli \
package-vmagent \
package-vmalert \
package-vmalert-tool \
@@ -169,9 +170,11 @@ vmutils-windows-amd64: \
vmrestore-windows-amd64 \
vmctl-windows-amd64
# When adding a new crossbuild target, please also add it to the .github/workflows/build.yml
crossbuild:
$(MAKE_PARALLEL) victoria-metrics-crossbuild vmutils-crossbuild
# When adding a new crossbuild target, please also add it to the .github/workflows/build.yml
victoria-metrics-crossbuild: \
victoria-metrics-linux-386 \
victoria-metrics-linux-amd64 \
@@ -184,6 +187,7 @@ victoria-metrics-crossbuild: \
victoria-metrics-openbsd-amd64 \
victoria-metrics-windows-amd64
# When adding a new crossbuild target, please also add it to the .github/workflows/build.yml
vmutils-crossbuild: \
vmutils-linux-386 \
vmutils-linux-amd64 \
@@ -196,12 +200,52 @@ vmutils-crossbuild: \
vmutils-openbsd-amd64 \
vmutils-windows-amd64
publish-final-images:
PKG_TAG=$(TAG) APP_NAME=victoria-metrics $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG) APP_NAME=vmagent $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG) APP_NAME=vmalert $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG) APP_NAME=vmalert-tool $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG) APP_NAME=vmauth $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG) APP_NAME=vmbackup $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG) APP_NAME=vmrestore $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG) APP_NAME=vmctl $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-cluster APP_NAME=vminsert $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-cluster APP_NAME=vmselect $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-cluster APP_NAME=vmstorage $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-enterprise APP_NAME=victoria-metrics $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-enterprise APP_NAME=vmagent $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-enterprise APP_NAME=vmalert $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-enterprise APP_NAME=vmauth $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-enterprise APP_NAME=vmbackup $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-enterprise APP_NAME=vmrestore $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-enterprise-cluster APP_NAME=vminsert $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-enterprise-cluster APP_NAME=vmselect $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-enterprise-cluster APP_NAME=vmstorage $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-enterprise APP_NAME=vmgateway $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG)-enterprise APP_NAME=vmbackupmanager $(MAKE) publish-via-docker-from-rc && \
PKG_TAG=$(TAG) $(MAKE) publish-latest
publish-latest:
PKG_TAG=$(TAG) APP_NAME=victoria-metrics $(MAKE) publish-via-docker-latest && \
PKG_TAG=$(TAG) APP_NAME=vmagent $(MAKE) publish-via-docker-latest && \
PKG_TAG=$(TAG) APP_NAME=vmalert $(MAKE) publish-via-docker-latest && \
PKG_TAG=$(TAG) APP_NAME=vmalert-tool $(MAKE) publish-via-docker-latest && \
PKG_TAG=$(TAG) APP_NAME=vmauth $(MAKE) publish-via-docker-latest && \
PKG_TAG=$(TAG) APP_NAME=vmbackup $(MAKE) publish-via-docker-latest && \
PKG_TAG=$(TAG) APP_NAME=vmrestore $(MAKE) publish-via-docker-latest && \
PKG_TAG=$(TAG) APP_NAME=vmctl $(MAKE) publish-via-docker-latest && \
PKG_TAG=$(TAG)-cluster APP_NAME=vminsert $(MAKE) publish-via-docker-latest && \
PKG_TAG=$(TAG)-cluster APP_NAME=vmselect $(MAKE) publish-via-docker-latest && \
PKG_TAG=$(TAG)-cluster APP_NAME=vmstorage $(MAKE) publish-via-docker-latest && \
PKG_TAG=$(TAG)-enterprise APP_NAME=vmgateway $(MAKE) publish-via-docker-latest
PKG_TAG=$(TAG)-enterprise APP_NAME=vmbackupmanager $(MAKE) publish-via-docker-latest
publish-release:
rm -rf bin/*
git checkout $(TAG) && $(MAKE) release && LATEST_TAG=stable $(MAKE) publish && \
git checkout $(TAG)-cluster && $(MAKE) release && LATEST_TAG=cluster-stable $(MAKE) publish && \
git checkout $(TAG)-enterprise && $(MAKE) release && LATEST_TAG=enterprise-stable $(MAKE) publish && \
git checkout $(TAG)-enterprise-cluster && $(MAKE) release && LATEST_TAG=enterprise-cluster-stable $(MAKE) publish
git checkout $(TAG) && $(MAKE) release && $(MAKE) publish && \
git checkout $(TAG)-cluster && $(MAKE) release && $(MAKE) publish && \
git checkout $(TAG)-enterprise && $(MAKE) release && $(MAKE) publish && \
git checkout $(TAG)-enterprise-cluster && $(MAKE) release && $(MAKE) publish
release:
$(MAKE_PARALLEL) \
@@ -265,128 +309,6 @@ release-victoria-metrics-windows-goarch: victoria-metrics-windows-$(GOARCH)-prod
cd bin && rm -rf \
victoria-metrics-windows-$(GOARCH)-prod.exe
release-victoria-logs-bundle: \
release-victoria-logs \
release-vlogscli
publish-victoria-logs-bundle: \
publish-victoria-logs \
publish-vlogscli
release-victoria-logs:
$(MAKE_PARALLEL) release-victoria-logs-linux-386 \
release-victoria-logs-linux-amd64 \
release-victoria-logs-linux-arm \
release-victoria-logs-linux-arm64 \
release-victoria-logs-darwin-amd64 \
release-victoria-logs-darwin-arm64 \
release-victoria-logs-freebsd-amd64 \
release-victoria-logs-openbsd-amd64 \
release-victoria-logs-windows-amd64
release-victoria-logs-linux-386:
GOOS=linux GOARCH=386 $(MAKE) release-victoria-logs-goos-goarch
release-victoria-logs-linux-amd64:
GOOS=linux GOARCH=amd64 $(MAKE) release-victoria-logs-goos-goarch
release-victoria-logs-linux-arm:
GOOS=linux GOARCH=arm $(MAKE) release-victoria-logs-goos-goarch
release-victoria-logs-linux-arm64:
GOOS=linux GOARCH=arm64 $(MAKE) release-victoria-logs-goos-goarch
release-victoria-logs-darwin-amd64:
GOOS=darwin GOARCH=amd64 $(MAKE) release-victoria-logs-goos-goarch
release-victoria-logs-darwin-arm64:
GOOS=darwin GOARCH=arm64 $(MAKE) release-victoria-logs-goos-goarch
release-victoria-logs-freebsd-amd64:
GOOS=freebsd GOARCH=amd64 $(MAKE) release-victoria-logs-goos-goarch
release-victoria-logs-openbsd-amd64:
GOOS=openbsd GOARCH=amd64 $(MAKE) release-victoria-logs-goos-goarch
release-victoria-logs-windows-amd64:
GOARCH=amd64 $(MAKE) release-victoria-logs-windows-goarch
release-victoria-logs-goos-goarch: victoria-logs-$(GOOS)-$(GOARCH)-prod
cd bin && \
tar $(TAR_OWNERSHIP) --transform="flags=r;s|-$(GOOS)-$(GOARCH)||" -czf victoria-logs-$(GOOS)-$(GOARCH)-$(PKG_TAG).tar.gz \
victoria-logs-$(GOOS)-$(GOARCH)-prod \
&& sha256sum victoria-logs-$(GOOS)-$(GOARCH)-$(PKG_TAG).tar.gz \
victoria-logs-$(GOOS)-$(GOARCH)-prod \
| sed s/-$(GOOS)-$(GOARCH)-prod/-prod/ > victoria-logs-$(GOOS)-$(GOARCH)-$(PKG_TAG)_checksums.txt
cd bin && rm -rf victoria-logs-$(GOOS)-$(GOARCH)-prod
release-victoria-logs-windows-goarch: victoria-logs-windows-$(GOARCH)-prod
cd bin && \
zip victoria-logs-windows-$(GOARCH)-$(PKG_TAG).zip \
victoria-logs-windows-$(GOARCH)-prod.exe \
&& sha256sum victoria-logs-windows-$(GOARCH)-$(PKG_TAG).zip \
victoria-logs-windows-$(GOARCH)-prod.exe \
> victoria-logs-windows-$(GOARCH)-$(PKG_TAG)_checksums.txt
cd bin && rm -rf \
victoria-logs-windows-$(GOARCH)-prod.exe
release-vlogscli:
$(MAKE_PARALLEL) release-vlogscli-linux-386 \
release-vlogscli-linux-amd64 \
release-vlogscli-linux-arm \
release-vlogscli-linux-arm64 \
release-vlogscli-darwin-amd64 \
release-vlogscli-darwin-arm64 \
release-vlogscli-freebsd-amd64 \
release-vlogscli-openbsd-amd64 \
release-vlogscli-windows-amd64
release-vlogscli-linux-386:
GOOS=linux GOARCH=386 $(MAKE) release-vlogscli-goos-goarch
release-vlogscli-linux-amd64:
GOOS=linux GOARCH=amd64 $(MAKE) release-vlogscli-goos-goarch
release-vlogscli-linux-arm:
GOOS=linux GOARCH=arm $(MAKE) release-vlogscli-goos-goarch
release-vlogscli-linux-arm64:
GOOS=linux GOARCH=arm64 $(MAKE) release-vlogscli-goos-goarch
release-vlogscli-darwin-amd64:
GOOS=darwin GOARCH=amd64 $(MAKE) release-vlogscli-goos-goarch
release-vlogscli-darwin-arm64:
GOOS=darwin GOARCH=arm64 $(MAKE) release-vlogscli-goos-goarch
release-vlogscli-freebsd-amd64:
GOOS=freebsd GOARCH=amd64 $(MAKE) release-vlogscli-goos-goarch
release-vlogscli-openbsd-amd64:
GOOS=openbsd GOARCH=amd64 $(MAKE) release-vlogscli-goos-goarch
release-vlogscli-windows-amd64:
GOARCH=amd64 $(MAKE) release-vlogscli-windows-goarch
release-vlogscli-goos-goarch: vlogscli-$(GOOS)-$(GOARCH)-prod
cd bin && \
tar $(TAR_OWNERSHIP) --transform="flags=r;s|-$(GOOS)-$(GOARCH)||" -czf vlogscli-$(GOOS)-$(GOARCH)-$(PKG_TAG).tar.gz \
vlogscli-$(GOOS)-$(GOARCH)-prod \
&& sha256sum vlogscli-$(GOOS)-$(GOARCH)-$(PKG_TAG).tar.gz \
vlogscli-$(GOOS)-$(GOARCH)-prod \
| sed s/-$(GOOS)-$(GOARCH)-prod/-prod/ > vlogscli-$(GOOS)-$(GOARCH)-$(PKG_TAG)_checksums.txt
cd bin && rm -rf vlogscli-$(GOOS)-$(GOARCH)-prod
release-vlogscli-windows-goarch: vlogscli-windows-$(GOARCH)-prod
cd bin && \
zip vlogscli-windows-$(GOARCH)-$(PKG_TAG).zip \
vlogscli-windows-$(GOARCH)-prod.exe \
&& sha256sum vlogscli-windows-$(GOARCH)-$(PKG_TAG).zip \
vlogscli-windows-$(GOARCH)-prod.exe \
> vlogscli-windows-$(GOARCH)-$(PKG_TAG)_checksums.txt
cd bin && rm -rf \
vlogscli-windows-$(GOARCH)-prod.exe
release-vmutils: \
release-vmutils-linux-386 \
release-vmutils-linux-amd64 \
@@ -504,7 +426,7 @@ fmt:
gofmt -l -w -s ./apptest
vet:
go vet ./lib/...
GOEXPERIMENT=synctest go vet ./lib/...
go vet ./app/...
go vet ./apptest/...
@@ -513,48 +435,52 @@ check-all: fmt vet golangci-lint govulncheck
clean-checkers: remove-golangci-lint remove-govulncheck
test:
go test ./lib/... ./app/...
GOEXPERIMENT=synctest go test ./lib/... ./app/...
test-race:
go test -race ./lib/... ./app/...
GOEXPERIMENT=synctest go test -race ./lib/... ./app/...
test-pure:
CGO_ENABLED=0 go test ./lib/... ./app/...
GOEXPERIMENT=synctest CGO_ENABLED=0 go test ./lib/... ./app/...
test-full:
go test -coverprofile=coverage.txt -covermode=atomic ./lib/... ./app/...
GOEXPERIMENT=synctest go test -coverprofile=coverage.txt -covermode=atomic ./lib/... ./app/...
test-full-386:
GOARCH=386 go test -coverprofile=coverage.txt -covermode=atomic ./lib/... ./app/...
GOEXPERIMENT=synctest GOARCH=386 go test -coverprofile=coverage.txt -covermode=atomic ./lib/... ./app/...
integration-test: victoria-metrics vmagent vmalert vmauth
integration-test:
$(MAKE) apptest
apptest:
$(MAKE) victoria-metrics vmagent vmalert vmauth vmctl vmbackup vmrestore
go test ./apptest/... -skip="^TestCluster.*"
benchmark:
go test -bench=. ./lib/...
GOEXPERIMENT=synctest go test -bench=. ./lib/...
go test -bench=. ./app/...
benchmark-pure:
CGO_ENABLED=0 go test -bench=. ./lib/...
GOEXPERIMENT=synctest CGO_ENABLED=0 go test -bench=. ./lib/...
CGO_ENABLED=0 go test -bench=. ./app/...
vendor-update:
go get -u ./lib/...
go get -u ./app/...
go mod tidy -compat=1.23
go mod tidy -compat=1.24
go mod vendor
app-local:
CGO_ENABLED=1 go build $(RACE) -ldflags "$(GO_BUILDINFO)" -o bin/$(APP_NAME)$(RACE) $(PKG_PREFIX)/app/$(APP_NAME)
CGO_ENABLED=1 go build $(RACE) -ldflags "$(GO_BUILDINFO)" -tags "$(EXTRA_GO_BUILD_TAGS)" -o bin/$(APP_NAME)$(RACE) $(PKG_PREFIX)/app/$(APP_NAME)
app-local-pure:
CGO_ENABLED=0 go build $(RACE) -ldflags "$(GO_BUILDINFO)" -o bin/$(APP_NAME)-pure$(RACE) $(PKG_PREFIX)/app/$(APP_NAME)
CGO_ENABLED=0 go build $(RACE) -ldflags "$(GO_BUILDINFO)" -tags "$(EXTRA_GO_BUILD_TAGS)" -o bin/$(APP_NAME)-pure$(RACE) $(PKG_PREFIX)/app/$(APP_NAME)
app-local-goos-goarch:
CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) go build $(RACE) -ldflags "$(GO_BUILDINFO)" -o bin/$(APP_NAME)-$(GOOS)-$(GOARCH)$(RACE) $(PKG_PREFIX)/app/$(APP_NAME)
CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) go build $(RACE) -ldflags "$(GO_BUILDINFO)" -tags "$(EXTRA_GO_BUILD_TAGS)" -o bin/$(APP_NAME)-$(GOOS)-$(GOARCH)$(RACE) $(PKG_PREFIX)/app/$(APP_NAME)
app-local-windows-goarch:
CGO_ENABLED=0 GOOS=windows GOARCH=$(GOARCH) go build $(RACE) -ldflags "$(GO_BUILDINFO)" -o bin/$(APP_NAME)-windows-$(GOARCH)$(RACE).exe $(PKG_PREFIX)/app/$(APP_NAME)
CGO_ENABLED=0 GOOS=windows GOARCH=$(GOARCH) go build $(RACE) -ldflags "$(GO_BUILDINFO)" -tags "$(EXTRA_GO_BUILD_TAGS)" -o bin/$(APP_NAME)-windows-$(GOARCH)$(RACE).exe $(PKG_PREFIX)/app/$(APP_NAME)
quicktemplate-gen: install-qtc
qtc
@@ -564,10 +490,10 @@ install-qtc:
golangci-lint: install-golangci-lint
golangci-lint run
GOEXPERIMENT=synctest golangci-lint run
install-golangci-lint:
which golangci-lint || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell go env GOPATH)/bin v1.64.7
which golangci-lint && (golangci-lint --version | grep -q $(GOLANGCI_LINT_VERSION)) || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell go env GOPATH)/bin v$(GOLANGCI_LINT_VERSION)
remove-golangci-lint:
rm -rf `which golangci-lint`

View File

@@ -1,19 +1,19 @@
# VictoriaMetrics
![Latest Release](https://img.shields.io/github/v/release/VictoriaMetrics/VictoriaMetrics?sort=semver&label=&filter=!*-victorialogs&logo=github&labelColor=gray&color=gray&link=https%3A%2F%2Fgithub.com%2FVictoriaMetrics%2FVictoriaMetrics%2Freleases%2Flatest)
[![Latest Release](https://img.shields.io/github/v/release/VictoriaMetrics/VictoriaMetrics?sort=semver&label=&filter=!*-victorialogs&logo=github&labelColor=gray&color=gray&link=https%3A%2F%2Fgithub.com%2FVictoriaMetrics%2FVictoriaMetrics%2Freleases%2Flatest)](https://github.com/VictoriaMetrics/VictoriaMetrics/releases)
![Docker Pulls](https://img.shields.io/docker/pulls/victoriametrics/victoria-metrics?label=&logo=docker&logoColor=white&labelColor=2496ED&color=2496ED&link=https%3A%2F%2Fhub.docker.com%2Fr%2Fvictoriametrics%2Fvictoria-metrics)
![Go Report](https://goreportcard.com/badge/github.com/VictoriaMetrics/VictoriaMetrics?link=https%3A%2F%2Fgoreportcard.com%2Freport%2Fgithub.com%2FVictoriaMetrics%2FVictoriaMetrics)
![Build Status](https://github.com/VictoriaMetrics/VictoriaMetrics/actions/workflows/main.yml/badge.svg?branch=master&link=https%3A%2F%2Fgithub.com%2FVictoriaMetrics%2FVictoriaMetrics%2Factions)
![codecov](https://codecov.io/gh/VictoriaMetrics/VictoriaMetrics/branch/master/graph/badge.svg?link=https%3A%2F%2Fcodecov.io%2Fgh%2FVictoriaMetrics%2FVictoriaMetrics)
![License](https://img.shields.io/github/license/VictoriaMetrics/VictoriaMetrics?labelColor=green&label=&link=https%3A%2F%2Fgithub.com%2FVictoriaMetrics%2FVictoriaMetrics%2Fblob%2Fmaster%2FLICENSE)
[![Go Report](https://goreportcard.com/badge/github.com/VictoriaMetrics/VictoriaMetrics?link=https%3A%2F%2Fgoreportcard.com%2Freport%2Fgithub.com%2FVictoriaMetrics%2FVictoriaMetrics)](https://goreportcard.com/report/github.com/VictoriaMetrics/VictoriaMetrics)
[![Build Status](https://github.com/VictoriaMetrics/VictoriaMetrics/actions/workflows/main.yml/badge.svg?branch=master&link=https%3A%2F%2Fgithub.com%2FVictoriaMetrics%2FVictoriaMetrics%2Factions)](https://github.com/VictoriaMetrics/VictoriaMetrics/actions/workflows/main.yml)
[![codecov](https://codecov.io/gh/VictoriaMetrics/VictoriaMetrics/branch/master/graph/badge.svg?link=https%3A%2F%2Fcodecov.io%2Fgh%2FVictoriaMetrics%2FVictoriaMetrics)](https://app.codecov.io/gh/VictoriaMetrics/VictoriaMetrics)
[![License](https://img.shields.io/github/license/VictoriaMetrics/VictoriaMetrics?labelColor=green&label=&link=https%3A%2F%2Fgithub.com%2FVictoriaMetrics%2FVictoriaMetrics%2Fblob%2Fmaster%2FLICENSE)](https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/LICENSE)
![Slack](https://img.shields.io/badge/Join-4A154B?logo=slack&link=https%3A%2F%2Fslack.victoriametrics.com)
![X](https://img.shields.io/twitter/follow/VictoriaMetrics?style=flat&label=Follow&color=black&logo=x&labelColor=black&link=https%3A%2F%2Fx.com%2FVictoriaMetrics)
![Reddit](https://img.shields.io/reddit/subreddit-subscribers/VictoriaMetrics?style=flat&label=Join&labelColor=red&logoColor=white&logo=reddit&link=https%3A%2F%2Fwww.reddit.com%2Fr%2FVictoriaMetrics)
[![X](https://img.shields.io/twitter/follow/VictoriaMetrics?style=flat&label=Follow&color=black&logo=x&labelColor=black&link=https%3A%2F%2Fx.com%2FVictoriaMetrics)](https://x.com/VictoriaMetrics/)
[![Reddit](https://img.shields.io/reddit/subreddit-subscribers/VictoriaMetrics?style=flat&label=Join&labelColor=red&logoColor=white&logo=reddit&link=https%3A%2F%2Fwww.reddit.com%2Fr%2FVictoriaMetrics)](https://www.reddit.com/r/VictoriaMetrics/)
<picture>
<source srcset="docs/logo_white.webp" media="(prefers-color-scheme: dark)">
<source srcset="docs/logo.webp" media="(prefers-color-scheme: light)">
<img src="docs/logo.webp" width="300" alt="VictoriaMetrics logo">
<source srcset="docs/victoriametrics/logo_white.webp" media="(prefers-color-scheme: dark)">
<source srcset="docs/victoriametrics/logo.webp" media="(prefers-color-scheme: light)">
<img src="docs/victoriametrics/logo.webp" width="300" alt="VictoriaMetrics logo">
</picture>
VictoriaMetrics is a fast, cost-saving, and scalable solution for monitoring and managing time series data. It delivers high performance and reliability, making it an ideal choice for businesses of all sizes.
@@ -21,10 +21,10 @@ VictoriaMetrics is a fast, cost-saving, and scalable solution for monitoring and
Here are some resources and information about VictoriaMetrics:
- Documentation: [docs.victoriametrics.com](https://docs.victoriametrics.com)
- Case studies: [Grammarly, Roblox, Wix,...](https://docs.victoriametrics.com/casestudies/).
- Case studies: [Grammarly, Roblox, Wix,...](https://docs.victoriametrics.com/victoriametrics/casestudies/).
- Available: [Binary releases](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest), docker images [Docker Hub](https://hub.docker.com/r/victoriametrics/victoria-metrics/) and [Quay](https://quay.io/repository/victoriametrics/victoria-metrics), [Source code](https://github.com/VictoriaMetrics/VictoriaMetrics)
- Deployment types: [Single-node version](https://docs.victoriametrics.com/), [Cluster version](https://docs.victoriametrics.com/cluster-victoriametrics/), and [Enterprise version](https://docs.victoriametrics.com/enterprise/)
- Changelog: [CHANGELOG](https://docs.victoriametrics.com/changelog/), and [How to upgrade](https://docs.victoriametrics.com/#how-to-upgrade-victoriametrics)
- Deployment types: [Single-node version](https://docs.victoriametrics.com/), [Cluster version](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/), and [Enterprise version](https://docs.victoriametrics.com/victoriametrics/enterprise/)
- Changelog: [CHANGELOG](https://docs.victoriametrics.com/victoriametrics/changelog/), and [How to upgrade](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#how-to-upgrade-victoriametrics)
- Community: [Slack](https://slack.victoriametrics.com/), [X (Twitter)](https://x.com/VictoriaMetrics), [LinkedIn](https://www.linkedin.com/company/victoriametrics/), [YouTube](https://www.youtube.com/@VictoriaMetrics)
Yes, we open-source both the single-node VictoriaMetrics and the cluster version.
@@ -35,22 +35,22 @@ VictoriaMetrics is optimized for timeseries data, even when old time series are
* **Long-term storage for Prometheus** or as a drop-in replacement for Prometheus and Graphite in Grafana.
* **Powerful stream aggregation**: Can be used as a StatsD alternative.
* **Ideal for big data**: Works well with large amounts of time series data from APM, Kubernetes, IoT sensors, connected cars, industrial telemetry, financial data and various [Enterprise workloads](https://docs.victoriametrics.com/enterprise/).
* **Ideal for big data**: Works well with large amounts of time series data from APM, Kubernetes, IoT sensors, connected cars, industrial telemetry, financial data and various [Enterprise workloads](https://docs.victoriametrics.com/victoriametrics/enterprise/).
* **Query language**: Supports both PromQL and the more performant MetricsQL.
* **Easy to setup**: No dependencies, single [small binary](https://medium.com/@valyala/stripping-dependency-bloat-in-victoriametrics-docker-image-983fb5912b0d), configuration through command-line flags, but the default is also fine-tuned; backup and restore with [instant snapshots](https://medium.com/@valyala/how-victoriametrics-makes-instant-snapshots-for-multi-terabyte-time-series-data-e1f3fb0e0282).
* **Global query view**: Multiple Prometheus instances or any other data sources may ingest data into VictoriaMetrics and queried via a single query.
* **Various Protocols**: Support metric scraping, ingestion and backfilling in various protocol.
* [Prometheus exporters](https://docs.victoriametrics.com/#how-to-scrape-prometheus-exporters-such-as-node-exporter), [Prometheus remote write API](https://docs.victoriametrics.com/#prometheus-setup), [Prometheus exposition format](https://docs.victoriametrics.com/#how-to-import-data-in-prometheus-exposition-format).
* [InfluxDB line protocol](https://docs.victoriametrics.com/#how-to-send-data-from-influxdb-compatible-agents-such-as-telegraf) over HTTP, TCP and UDP.
* [Graphite plaintext protocol](https://docs.victoriametrics.com/#how-to-send-data-from-graphite-compatible-agents-such-as-statsd) with [tags](https://graphite.readthedocs.io/en/latest/tags.html#carbon).
* [OpenTSDB put message](https://docs.victoriametrics.com/#sending-data-via-telnet-put-protocol).
* [HTTP OpenTSDB /api/put requests](https://docs.victoriametrics.com/#sending-opentsdb-data-via-http-apiput-requests).
* [JSON line format](https://docs.victoriametrics.com/#how-to-import-data-in-json-line-format).
* [Arbitrary CSV data](https://docs.victoriametrics.com/#how-to-import-csv-data).
* [Native binary format](https://docs.victoriametrics.com/#how-to-import-data-in-native-format).
* [DataDog agent or DogStatsD](https://docs.victoriametrics.com/#how-to-send-data-from-datadog-agent).
* [NewRelic infrastructure agent](https://docs.victoriametrics.com/#how-to-send-data-from-newrelic-agent).
* [OpenTelemetry metrics format](https://docs.victoriametrics.com/#sending-data-via-opentelemetry).
* [Prometheus exporters](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#how-to-scrape-prometheus-exporters-such-as-node-exporter), [Prometheus remote write API](https://docs.victoriametrics.com/victoriametrics/integrations/prometheus/), [Prometheus exposition format](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#how-to-import-data-in-prometheus-exposition-format).
* [InfluxDB line protocol](https://docs.victoriametrics.com/victoriametrics/integrations/influxdb/) over HTTP, TCP and UDP.
* [Graphite plaintext protocol](https://docs.victoriametrics.com/victoriametrics/integrations/graphite/#ingesting) with [tags](https://graphite.readthedocs.io/en/latest/tags.html#carbon).
* [OpenTSDB put message](https://docs.victoriametrics.com/victoriametrics/integrations/opentsdb/#sending-data-via-telnet).
* [HTTP OpenTSDB /api/put requests](https://docs.victoriametrics.com/victoriametrics/integrations/opentsdb/#sending-data-via-http).
* [JSON line format](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#how-to-import-data-in-json-line-format).
* [Arbitrary CSV data](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#how-to-import-csv-data).
* [Native binary format](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#how-to-import-data-in-native-format).
* [DataDog agent or DogStatsD](https://docs.victoriametrics.com/victoriametrics/integrations/datadog/).
* [NewRelic infrastructure agent](https://docs.victoriametrics.com/victoriametrics/integrations/newrelic/#sending-data-from-agent).
* [OpenTelemetry metrics format](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#sending-data-via-opentelemetry).
* **NFS-based storages**: Supports storing data on NFS-based storages such as Amazon EFS, Google Filestore.
* And many other features such as metrics relabeling, cardinality limiter, etc.
@@ -62,9 +62,9 @@ In addition, the Enterprise version includes extra features:
- **Backup automation**: Automates regular backup procedures.
- **Multiple retentions**: Reducing storage costs by specifying different retentions for different datasets.
- **Downsampling**: Reducing storage costs and increasing performance for queries over historical data.
- **Stable releases** with long-term support lines ([LTS](https://docs.victoriametrics.com/lts-releases/)).
- **Stable releases** with long-term support lines ([LTS](https://docs.victoriametrics.com/victoriametrics/lts-releases/)).
- **Comprehensive support**: First-class consulting, feature requests and technical support provided by the core VictoriaMetrics dev team.
- Many other features, which you can read about on [the Enterprise page](https://docs.victoriametrics.com/enterprise/).
- Many other features, which you can read about on [the Enterprise page](https://docs.victoriametrics.com/victoriametrics/enterprise/).
[Contact us](mailto:info@victoriametrics.com) if you need enterprise support for VictoriaMetrics. Or you can request a free trial license [here](https://victoriametrics.com/products/enterprise/trial/), downloaded Enterprise binaries are available at [Github Releases](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/latest).
@@ -77,7 +77,7 @@ Some good benchmarks VictoriaMetrics achieved:
* **Minimal memory footprint**: handling millions of unique timeseries with [10x less RAM](https://medium.com/@valyala/insert-benchmarks-with-inch-influxdb-vs-victoriametrics-e31a41ae2893) than InfluxDB, up to [7x less RAM](https://valyala.medium.com/prometheus-vs-victoriametrics-benchmark-on-node-exporter-metrics-4ca29c75590f) than Prometheus, Thanos or Cortex.
* **Highly scalable and performance** for [data ingestion](https://medium.com/@valyala/high-cardinality-tsdb-benchmarks-victoriametrics-vs-timescaledb-vs-influxdb-13e6ee64dd6b) and [querying](https://medium.com/@valyala/when-size-matters-benchmarking-victoriametrics-vs-timescale-and-influxdb-6035811952d4), [20x outperforms](https://medium.com/@valyala/insert-benchmarks-with-inch-influxdb-vs-victoriametrics-e31a41ae2893) InfluxDB and TimescaleDB.
* **High data compression**: [70x more data points](https://medium.com/@valyala/when-size-matters-benchmarking-victoriametrics-vs-timescale-and-influxdb-6035811952d4) may be stored into limited storage than TimescaleDB, [7x less storage](https://valyala.medium.com/prometheus-vs-victoriametrics-benchmark-on-node-exporter-metrics-4ca29c75590f) space is required than Prometheus, Thanos or Cortex.
* **Reducing storage costs**: [10x more effective](https://docs.victoriametrics.com/casestudies/#grammarly) than Graphite according to the Grammarly case study.
* **Reducing storage costs**: [10x more effective](https://docs.victoriametrics.com/victoriametrics/casestudies/#grammarly) than Graphite according to the Grammarly case study.
* **A single-node VictoriaMetrics** can replace medium-sized clusters built with competing solutions such as Thanos, M3DB, Cortex, InfluxDB or TimescaleDB. See [VictoriaMetrics vs Thanos](https://medium.com/@valyala/comparing-thanos-to-victoriametrics-cluster-b193bea1683), [Measuring vertical scalability](https://medium.com/@valyala/measuring-vertical-scalability-for-time-series-databases-in-google-cloud-92550d78d8ae), [Remote write storage wars - PromCon 2019](https://promcon.io/2019-munich/talks/remote-write-storage-wars/).
* **Optimized for storage**: [Works well with high-latency IO](https://medium.com/@valyala/high-cardinality-tsdb-benchmarks-victoriametrics-vs-timescaledb-vs-influxdb-13e6ee64dd6b) and low IOPS (HDD and network storage in AWS, Google Cloud, Microsoft Azure, etc.).
@@ -93,7 +93,7 @@ Feel free asking any questions regarding VictoriaMetrics:
* [Telegram-ru](https://t.me/VictoriaMetrics_ru1)
* [Mastodon](https://mastodon.social/@victoriametrics/)
If you like VictoriaMetrics and want to contribute, then please [read these docs](https://docs.victoriametrics.com/contributing/).
If you like VictoriaMetrics and want to contribute, then please [read these docs](https://docs.victoriametrics.com/victoriametrics/contributing/).
## VictoriaMetrics Logo

View File

@@ -6,9 +6,9 @@ The following versions of VictoriaMetrics receive regular security fixes:
| Version | Supported |
|---------|--------------------|
| [latest release](https://docs.victoriametrics.com/changelog/) | :white_check_mark: |
| v1.102.x [LTS line](https://docs.victoriametrics.com/lts-releases/) | :white_check_mark: |
| v1.110.x [LTS line](https://docs.victoriametrics.com/lts-releases/) | :white_check_mark: |
| [latest release](https://docs.victoriametrics.com/victoriametrics/changelog/) | :white_check_mark: |
| v1.102.x [LTS line](https://docs.victoriametrics.com/victoriametrics/lts-releases/) | :white_check_mark: |
| v1.110.x [LTS line](https://docs.victoriametrics.com/victoriametrics/lts-releases/) | :white_check_mark: |
| other releases | :x: |
See [this page](https://victoriametrics.com/security/) for more details.

View File

@@ -1,113 +0,0 @@
# All these commands must run from repository root.
victoria-logs:
APP_NAME=victoria-logs $(MAKE) app-local
victoria-logs-race:
APP_NAME=victoria-logs RACE=-race $(MAKE) app-local
victoria-logs-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker
victoria-logs-pure-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker-pure
victoria-logs-linux-amd64-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker-linux-amd64
victoria-logs-linux-arm-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker-linux-arm
victoria-logs-linux-arm64-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker-linux-arm64
victoria-logs-linux-ppc64le-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker-linux-ppc64le
victoria-logs-linux-386-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker-linux-386
victoria-logs-darwin-amd64-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker-darwin-amd64
victoria-logs-darwin-arm64-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker-darwin-arm64
victoria-logs-freebsd-amd64-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker-freebsd-amd64
victoria-logs-openbsd-amd64-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker-openbsd-amd64
victoria-logs-windows-amd64-prod:
APP_NAME=victoria-logs $(MAKE) app-via-docker-windows-amd64
package-victoria-logs:
APP_NAME=victoria-logs $(MAKE) package-via-docker
package-victoria-logs-pure:
APP_NAME=victoria-logs $(MAKE) package-via-docker-pure
package-victoria-logs-amd64:
APP_NAME=victoria-logs $(MAKE) package-via-docker-amd64
package-victoria-logs-arm:
APP_NAME=victoria-logs $(MAKE) package-via-docker-arm
package-victoria-logs-arm64:
APP_NAME=victoria-logs $(MAKE) package-via-docker-arm64
package-victoria-logs-ppc64le:
APP_NAME=victoria-logs $(MAKE) package-via-docker-ppc64le
package-victoria-logs-386:
APP_NAME=victoria-logs $(MAKE) package-via-docker-386
publish-victoria-logs:
APP_NAME=victoria-logs $(MAKE) publish-via-docker
victoria-logs-linux-amd64:
APP_NAME=victoria-logs CGO_ENABLED=1 GOOS=linux GOARCH=amd64 $(MAKE) app-local-goos-goarch
victoria-logs-linux-arm:
APP_NAME=victoria-logs CGO_ENABLED=0 GOOS=linux GOARCH=arm $(MAKE) app-local-goos-goarch
victoria-logs-linux-arm64:
APP_NAME=victoria-logs CGO_ENABLED=0 GOOS=linux GOARCH=arm64 $(MAKE) app-local-goos-goarch
victoria-logs-linux-ppc64le:
APP_NAME=victoria-logs CGO_ENABLED=0 GOOS=linux GOARCH=ppc64le $(MAKE) app-local-goos-goarch
victoria-logs-linux-s390x:
APP_NAME=victoria-logs CGO_ENABLED=0 GOOS=linux GOARCH=s390x $(MAKE) app-local-goos-goarch
victoria-logs-linux-loong64:
APP_NAME=victoria-logs CGO_ENABLED=0 GOOS=linux GOARCH=loong64 $(MAKE) app-local-goos-goarch
victoria-logs-linux-386:
APP_NAME=victoria-logs CGO_ENABLED=0 GOOS=linux GOARCH=386 $(MAKE) app-local-goos-goarch
victoria-logs-darwin-amd64:
APP_NAME=victoria-logs CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 $(MAKE) app-local-goos-goarch
victoria-logs-darwin-arm64:
APP_NAME=victoria-logs CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 $(MAKE) app-local-goos-goarch
victoria-logs-freebsd-amd64:
APP_NAME=victoria-logs CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 $(MAKE) app-local-goos-goarch
victoria-logs-openbsd-amd64:
APP_NAME=victoria-logs CGO_ENABLED=0 GOOS=openbsd GOARCH=amd64 $(MAKE) app-local-goos-goarch
victoria-logs-windows-amd64:
GOARCH=amd64 APP_NAME=victoria-logs $(MAKE) app-local-windows-goarch
victoria-logs-pure:
APP_NAME=victoria-logs $(MAKE) app-local-pure
run-victoria-logs:
mkdir -p victoria-logs-data
DOCKER_OPTS='-v $(shell pwd)/victoria-logs-data:/victoria-logs-data' \
APP_NAME=victoria-logs \
ARGS='' \
$(MAKE) run-via-docker

View File

@@ -0,0 +1 @@
VictoriaLogs source code has been moved to [github.com/VictoriaMetrics/VictoriaLogs](https://github.com/VictoriaMetrics/VictoriaLogs/).

View File

@@ -1,8 +0,0 @@
ARG base_image=non-existing
FROM $base_image
EXPOSE 9428
ENTRYPOINT ["/victoria-logs-prod"]
ARG src_binary=non-existing
COPY $src_binary ./victoria-logs-prod

View File

@@ -1,108 +0,0 @@
package main
import (
"flag"
"fmt"
"net/http"
"os"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlselect"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/buildinfo"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/envflag"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fs"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/procutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/pushmetrics"
)
var (
httpListenAddrs = flagutil.NewArrayString("httpListenAddr", "TCP address to listen for incoming http requests. See also -httpListenAddr.useProxyProtocol")
useProxyProtocol = flagutil.NewArrayBool("httpListenAddr.useProxyProtocol", "Whether to use proxy protocol for connections accepted at the given -httpListenAddr . "+
"See https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt . "+
"With enabled proxy protocol http server cannot serve regular /metrics endpoint. Use -pushmetrics.url for metrics pushing")
)
func main() {
// Write flags and help message to stdout, since it is easier to grep or pipe.
flag.CommandLine.SetOutput(os.Stdout)
flag.Usage = usage
envflag.Parse()
buildinfo.Init()
logger.Init()
listenAddrs := *httpListenAddrs
if len(listenAddrs) == 0 {
listenAddrs = []string{":9428"}
}
logger.Infof("starting VictoriaLogs at %q...", listenAddrs)
startTime := time.Now()
vlstorage.Init()
vlselect.Init()
vlinsert.Init()
go httpserver.Serve(listenAddrs, useProxyProtocol, requestHandler)
logger.Infof("started VictoriaLogs in %.3f seconds; see https://docs.victoriametrics.com/victorialogs/", time.Since(startTime).Seconds())
pushmetrics.Init()
sig := procutil.WaitForSigterm()
logger.Infof("received signal %s", sig)
pushmetrics.Stop()
logger.Infof("gracefully shutting down webservice at %q", listenAddrs)
startTime = time.Now()
if err := httpserver.Stop(listenAddrs); err != nil {
logger.Fatalf("cannot stop the webservice: %s", err)
}
logger.Infof("successfully shut down the webservice in %.3f seconds", time.Since(startTime).Seconds())
vlinsert.Stop()
vlselect.Stop()
vlstorage.Stop()
fs.MustStopDirRemover()
logger.Infof("the VictoriaLogs has been stopped in %.3f seconds", time.Since(startTime).Seconds())
}
func requestHandler(w http.ResponseWriter, r *http.Request) bool {
if r.URL.Path == "/" {
if r.Method != http.MethodGet {
return false
}
w.Header().Add("Content-Type", "text/html; charset=utf-8")
fmt.Fprintf(w, "<h2>Single-node VictoriaLogs</h2></br>")
fmt.Fprintf(w, "See docs at <a href='https://docs.victoriametrics.com/victorialogs/'>https://docs.victoriametrics.com/victorialogs/</a></br>")
fmt.Fprintf(w, "Useful endpoints:</br>")
httpserver.WriteAPIHelp(w, [][2]string{
{"select/vmui", "Web UI for VictoriaLogs"},
{"metrics", "available service metrics"},
{"flags", "command-line flags"},
})
return true
}
if vlinsert.RequestHandler(w, r) {
return true
}
if vlselect.RequestHandler(w, r) {
return true
}
if vlstorage.RequestHandler(w, r) {
return true
}
return false
}
func usage() {
const s = `
victoria-logs is a log management and analytics service.
See the docs at https://docs.victoriametrics.com/victorialogs/
`
flagutil.Usage(s)
}

View File

@@ -1,12 +0,0 @@
# See https://medium.com/on-docker/use-multi-stage-builds-to-inject-ca-certs-ad1e8f01de1b
ARG certs_image=non-existing
ARG root_image=non-existing
FROM $certs_image AS certs
RUN apk update && apk upgrade && apk --update --no-cache add ca-certificates
FROM $root_image
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
EXPOSE 9428
ENTRYPOINT ["/victoria-logs-prod"]
ARG TARGETARCH
COPY victoria-logs-linux-${TARGETARCH}-prod ./victoria-logs-prod

View File

@@ -17,7 +17,6 @@ import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/cgroup"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/envflag"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fs"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/procutil"
@@ -32,7 +31,7 @@ var (
"See https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt . "+
"With enabled proxy protocol http server cannot serve regular /metrics endpoint. Use -pushmetrics.url for metrics pushing")
minScrapeInterval = flag.Duration("dedup.minScrapeInterval", 0, "Leave only the last sample in every time series per each discrete interval "+
"equal to -dedup.minScrapeInterval > 0. See also -streamAggr.dedupInterval and https://docs.victoriametrics.com/#deduplication")
"equal to -dedup.minScrapeInterval > 0. See also -streamAggr.dedupInterval and https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#deduplication")
dryRun = flag.Bool("dryRun", false, "Whether to check config files without running VictoriaMetrics. The following config files are checked: "+
"-promscrape.config, -relabelConfig and -streamAggr.config. Unknown config entries aren't allowed in -promscrape.config by default. "+
"This can be changed with -promscrape.config.strictParse=false command-line flag")
@@ -45,7 +44,7 @@ var (
finalDedupScheduleInterval = flag.Duration("storage.finalDedupScheduleCheckInterval", time.Hour, "The interval for checking when final deduplication process should be started."+
"Storage unconditionally adds 25% jitter to the interval value on each check evaluation."+
" Changing the interval to the bigger values may delay downsampling, deduplication for historical data."+
" See also https://docs.victoriametrics.com/#deduplication")
" See also https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#deduplication")
)
func main() {
@@ -101,7 +100,9 @@ func main() {
startSelfScraper()
go httpserver.Serve(listenAddrs, useProxyProtocol, requestHandler)
go httpserver.Serve(listenAddrs, requestHandler, httpserver.ServeOptions{
UseProxyProtocol: useProxyProtocol,
})
logger.Infof("started VictoriaMetrics in %.3f seconds", time.Since(startTime).Seconds())
pushmetrics.Init()
@@ -123,8 +124,6 @@ func main() {
vmstorage.Stop()
vmselect.Stop()
fs.MustStopDirRemover()
logger.Infof("the VictoriaMetrics has been stopped in %.3f seconds", time.Since(startTime).Seconds())
}

View File

@@ -1,619 +0,0 @@
package main
import (
"bytes"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"log"
"math/rand"
"net"
"net/http"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"testing"
"time"
testutil "github.com/VictoriaMetrics/VictoriaMetrics/app/victoria-metrics/test"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vminsert"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmselect"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmselect/promql"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fs"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
)
const (
testFixturesDir = "testdata"
testStorageSuffix = "vm-test-storage"
testHTTPListenAddr = ":7654"
testStatsDListenAddr = ":2003"
testOpenTSDBListenAddr = ":4242"
testOpenTSDBHTTPListenAddr = ":4243"
testLogLevel = "INFO"
)
const (
testReadHTTPPath = "http://127.0.0.1" + testHTTPListenAddr
testWriteHTTPPath = "http://127.0.0.1" + testHTTPListenAddr + "/write"
testOpenTSDBWriteHTTPPath = "http://127.0.0.1" + testOpenTSDBHTTPListenAddr + "/api/put"
testPromWriteHTTPPath = "http://127.0.0.1" + testHTTPListenAddr + "/api/v1/write"
testImportCSVWriteHTTPPath = "http://127.0.0.1" + testHTTPListenAddr + "/api/v1/import/csv"
testHealthHTTPPath = "http://127.0.0.1" + testHTTPListenAddr + "/health"
)
const (
testStorageInitTimeout = 10 * time.Second
)
var (
storagePath string
insertionTime = time.Now().UTC()
)
type test struct {
Name string `json:"name"`
Data []string `json:"data"`
InsertQuery string `json:"insert_query"`
Query []string `json:"query"`
ResultMetrics []Metric `json:"result_metrics"`
ResultSeries Series `json:"result_series"`
ResultQuery Query `json:"result_query"`
Issue string `json:"issue"`
ExpectedResultLinesCount int `json:"expected_result_lines_count"`
}
type Metric struct {
Metric map[string]string `json:"metric"`
Values []float64 `json:"values"`
Timestamps []int64 `json:"timestamps"`
}
func (r *Metric) UnmarshalJSON(b []byte) error {
type plain Metric
return json.Unmarshal(testutil.PopulateTimeTpl(b, insertionTime), (*plain)(r))
}
type Series struct {
Status string `json:"status"`
Data []map[string]string `json:"data"`
}
type Query struct {
Status string `json:"status"`
Data struct {
ResultType string `json:"resultType"`
Result json.RawMessage `json:"result"`
} `json:"data"`
}
const rtVector, rtMatrix = "vector", "matrix"
func (q *Query) metrics() ([]Metric, error) {
switch q.Data.ResultType {
case rtVector:
var r QueryInstant
if err := json.Unmarshal(q.Data.Result, &r.Result); err != nil {
return nil, err
}
return r.metrics()
case rtMatrix:
var r QueryRange
if err := json.Unmarshal(q.Data.Result, &r.Result); err != nil {
return nil, err
}
return r.metrics()
default:
return nil, fmt.Errorf("unknown result type %q", q.Data.ResultType)
}
}
type QueryInstant struct {
Result []struct {
Labels map[string]string `json:"metric"`
TV [2]any `json:"value"`
} `json:"result"`
}
func (q QueryInstant) metrics() ([]Metric, error) {
result := make([]Metric, len(q.Result))
for i, res := range q.Result {
f, err := strconv.ParseFloat(res.TV[1].(string), 64)
if err != nil {
return nil, fmt.Errorf("metric %v, unable to parse float64 from %s: %w", res, res.TV[1], err)
}
var m Metric
m.Metric = res.Labels
m.Timestamps = append(m.Timestamps, int64(res.TV[0].(float64)))
m.Values = append(m.Values, f)
result[i] = m
}
return result, nil
}
type QueryRange struct {
Result []struct {
Metric map[string]string `json:"metric"`
Values [][]any `json:"values"`
} `json:"result"`
}
func (q QueryRange) metrics() ([]Metric, error) {
var result []Metric
for i, res := range q.Result {
var m Metric
for _, tv := range res.Values {
f, err := strconv.ParseFloat(tv[1].(string), 64)
if err != nil {
return nil, fmt.Errorf("metric %v, unable to parse float64 from %s: %w", res, tv[1], err)
}
m.Values = append(m.Values, f)
m.Timestamps = append(m.Timestamps, int64(tv[0].(float64)))
}
if len(m.Values) < 1 || len(m.Timestamps) < 1 {
return nil, fmt.Errorf("metric %v contains no values", res)
}
m.Metric = q.Result[i].Metric
result = append(result, m)
}
return result, nil
}
func (q *Query) UnmarshalJSON(b []byte) error {
type plain Query
return json.Unmarshal(testutil.PopulateTimeTpl(b, insertionTime), (*plain)(q))
}
func TestMain(m *testing.M) {
setUp()
code := m.Run()
tearDown()
os.Exit(code)
}
func setUp() {
storagePath = filepath.Join(os.TempDir(), testStorageSuffix)
processFlags()
logger.Init()
vmstorage.Init(promql.ResetRollupResultCacheIfNeeded)
vmselect.Init()
vminsert.Init()
go httpserver.Serve(*httpListenAddrs, useProxyProtocol, requestHandler)
readyStorageCheckFunc := func() bool {
resp, err := http.Get(testHealthHTTPPath)
if err != nil {
return false
}
_ = resp.Body.Close()
return resp.StatusCode == 200
}
if err := waitFor(testStorageInitTimeout, readyStorageCheckFunc); err != nil {
log.Fatalf("http server can't start for %s seconds, err %s", testStorageInitTimeout, err)
}
}
func processFlags() {
flag.Parse()
for _, fv := range []struct {
flag string
value string
}{
{flag: "storageDataPath", value: storagePath},
{flag: "httpListenAddr", value: testHTTPListenAddr},
{flag: "graphiteListenAddr", value: testStatsDListenAddr},
{flag: "opentsdbListenAddr", value: testOpenTSDBListenAddr},
{flag: "loggerLevel", value: testLogLevel},
{flag: "opentsdbHTTPListenAddr", value: testOpenTSDBHTTPListenAddr},
} {
// panics if flag doesn't exist
if err := flag.Lookup(fv.flag).Value.Set(fv.value); err != nil {
log.Fatalf("unable to set %q with value %q, err: %v", fv.flag, fv.value, err)
}
}
}
func waitFor(timeout time.Duration, f func() bool) error {
fraction := timeout / 10
for i := fraction; i < timeout; i += fraction {
if f() {
return nil
}
time.Sleep(fraction)
}
return fmt.Errorf("timeout")
}
func tearDown() {
if err := httpserver.Stop(*httpListenAddrs); err != nil {
log.Printf("cannot stop the webservice: %s", err)
}
vminsert.Stop()
vmstorage.Stop()
vmselect.Stop()
fs.MustRemoveAll(storagePath)
}
func TestWriteRead(t *testing.T) {
t.Run("write", testWrite)
time.Sleep(500 * time.Millisecond)
vmstorage.Storage.DebugFlush()
time.Sleep(1500 * time.Millisecond)
t.Run("read", testRead)
}
func testWrite(t *testing.T) {
t.Run("prometheus", func(t *testing.T) {
for _, test := range readIn("prometheus", insertionTime) {
if test.Data == nil {
continue
}
r := testutil.WriteRequest{}
testData := strings.Join(test.Data, "\n")
if err := json.Unmarshal([]byte(testData), &r.Timeseries); err != nil {
panic(fmt.Errorf("BUG: cannot unmarshal TimeSeries: %s\ntest data\n%s", err, testData))
}
if n := len(r.Timeseries); n <= 0 {
panic(fmt.Errorf("BUG: expecting non-empty Timeseries in test data:\n%s", testData))
}
data := testutil.Compress(r)
httpWrite(t, testPromWriteHTTPPath, test.InsertQuery, bytes.NewBuffer(data))
}
})
t.Run("csv", func(t *testing.T) {
for _, test := range readIn("csv", insertionTime) {
if test.Data == nil {
continue
}
httpWrite(t, testImportCSVWriteHTTPPath, test.InsertQuery, bytes.NewBuffer([]byte(strings.Join(test.Data, "\n"))))
}
})
t.Run("influxdb", func(t *testing.T) {
for _, x := range readIn("influxdb", insertionTime) {
test := x
t.Run(test.Name, func(t *testing.T) {
t.Parallel()
httpWrite(t, testWriteHTTPPath, test.InsertQuery, bytes.NewBufferString(strings.Join(test.Data, "\n")))
})
}
})
t.Run("graphite", func(t *testing.T) {
for _, x := range readIn("graphite", insertionTime) {
test := x
t.Run(test.Name, func(t *testing.T) {
t.Parallel()
tcpWrite(t, "127.0.0.1"+testStatsDListenAddr, strings.Join(test.Data, "\n"))
})
}
})
t.Run("opentsdb", func(t *testing.T) {
for _, x := range readIn("opentsdb", insertionTime) {
test := x
t.Run(test.Name, func(t *testing.T) {
t.Parallel()
tcpWrite(t, "127.0.0.1"+testOpenTSDBListenAddr, strings.Join(test.Data, "\n"))
})
}
})
t.Run("opentsdbhttp", func(t *testing.T) {
for _, x := range readIn("opentsdbhttp", insertionTime) {
test := x
t.Run(test.Name, func(t *testing.T) {
t.Parallel()
logger.Infof("writing %s", test.Data)
httpWrite(t, testOpenTSDBWriteHTTPPath, test.InsertQuery, bytes.NewBufferString(strings.Join(test.Data, "\n")))
})
}
})
}
func testRead(t *testing.T) {
for _, engine := range []string{"csv", "prometheus", "graphite", "opentsdb", "influxdb", "opentsdbhttp"} {
t.Run(engine, func(t *testing.T) {
for _, x := range readIn(engine, insertionTime) {
test := x
t.Run(test.Name, func(t *testing.T) {
t.Parallel()
for _, q := range test.Query {
q = testutil.PopulateTimeTplString(q, insertionTime)
if test.Issue != "" {
test.Issue = "\nRegression in " + test.Issue
}
switch {
case strings.HasPrefix(q, "/api/v1/export/csv"):
data := strings.Split(string(httpReadData(t, testReadHTTPPath, q)), "\n")
if len(data) == test.ExpectedResultLinesCount {
t.Fatalf("not expected number of csv lines want=%d\ngot=%d test=%s.%s\n\response=%q", len(data), test.ExpectedResultLinesCount, q, test.Issue, strings.Join(data, "\n"))
}
case strings.HasPrefix(q, "/api/v1/export"):
if err := checkMetricsResult(httpReadMetrics(t, testReadHTTPPath, q), test.ResultMetrics); err != nil {
t.Fatalf("Export. %s fails with error %s.%s", q, err, test.Issue)
}
case strings.HasPrefix(q, "/api/v1/series"):
s := Series{}
httpReadStruct(t, testReadHTTPPath, q, &s)
if err := checkSeriesResult(s, test.ResultSeries); err != nil {
t.Fatalf("Series. %s fails with error %s.%s", q, err, test.Issue)
}
case strings.HasPrefix(q, "/api/v1/query"):
queryResult := Query{}
httpReadStruct(t, testReadHTTPPath, q, &queryResult)
gotMetrics, err := queryResult.metrics()
if err != nil {
t.Fatalf("failed to parse query response: %s", err)
}
expMetrics, err := test.ResultQuery.metrics()
if err != nil {
t.Fatalf("failed to parse expected response: %s", err)
}
if err := checkMetricsResult(gotMetrics, expMetrics); err != nil {
t.Fatalf("%q fails with error %s.%s", q, err, test.Issue)
}
default:
t.Fatalf("unsupported read query %s", q)
}
}
})
}
})
}
}
func readIn(readFor string, insertTime time.Time) []test {
testDir := filepath.Join(testFixturesDir, readFor)
var tt []test
err := filepath.Walk(testDir, func(path string, _ os.FileInfo, err error) error {
if err != nil {
return err
}
if filepath.Ext(path) != ".json" {
return nil
}
b, err := os.ReadFile(path)
if err != nil {
panic(fmt.Errorf("BUG: cannot read %s: %s", path, err))
}
item := test{}
if err := json.Unmarshal(b, &item); err != nil {
panic(fmt.Errorf("cannot parse %T from %s: %s; data:\n%s", &item, path, err, b))
}
for i := range item.Data {
item.Data[i] = testutil.PopulateTimeTplString(item.Data[i], insertTime)
}
tt = append(tt, item)
return nil
})
if err != nil {
panic(fmt.Errorf("BUG: cannot read test data at %s: %w", testDir, err))
}
if len(tt) == 0 {
panic(fmt.Errorf("BUG: no tests found in %s", testDir))
}
return tt
}
func httpWrite(t *testing.T, address, query string, r io.Reader) {
t.Helper()
requestURL := address + query
resp, err := http.Post(requestURL, "", r)
if err != nil {
t.Fatalf("cannot send request to %s: %s", requestURL, err)
}
_ = resp.Body.Close()
if resp.StatusCode != 204 {
t.Fatalf("unexpected status code received from %s; got %d; want 204", requestURL, resp.StatusCode)
}
}
func tcpWrite(t *testing.T, address, data string) {
t.Helper()
conn, err := net.Dial("tcp", address)
if err != nil {
t.Fatalf("cannot dial %s: %s", address, err)
}
defer func() {
_ = conn.Close()
}()
n, err := conn.Write([]byte(data))
if err != nil {
t.Fatalf("cannot write %d bytes to %s: %s", len(data), address, err)
}
if n != len(data) {
panic(fmt.Errorf("BUG: conn.Write() returned unexpected number of written bytes to %s; got %d; want %d", address, n, len(data)))
}
}
func httpReadMetrics(t *testing.T, address, query string) []Metric {
t.Helper()
requestURL := address + query
resp, err := http.Get(requestURL)
if err != nil {
t.Fatalf("cannot send request to %s: %s", requestURL, err)
}
defer func() {
_ = resp.Body.Close()
}()
if resp.StatusCode != 200 {
t.Fatalf("unexpected status code received from %s; got %d; want 200", requestURL, resp.StatusCode)
}
var rows []Metric
dec := json.NewDecoder(resp.Body)
for {
var row Metric
err := dec.Decode(&row)
if err != nil {
if errors.Is(err, io.EOF) {
return rows
}
t.Fatalf("cannot decode %T from response received from %s: %s", &row, requestURL, err)
}
rows = append(rows, row)
}
}
func httpReadStruct(t *testing.T, address, query string, dst any) {
t.Helper()
requestURL := address + query
resp, err := http.Get(requestURL)
if err != nil {
t.Fatalf("cannot send request to %s: %s", requestURL, err)
}
defer func() {
_ = resp.Body.Close()
}()
if resp.StatusCode != 200 {
t.Fatalf("unexpected status code received from %s; got %d; want 200", requestURL, resp.StatusCode)
}
err = json.NewDecoder(resp.Body).Decode(dst)
if err != nil {
t.Fatalf("cannot decode %T from response received from %s: %s", dst, requestURL, err)
}
}
func httpReadData(t *testing.T, address, query string) []byte {
t.Helper()
requestURL := address + query
resp, err := http.Get(requestURL)
if err != nil {
t.Fatalf("cannot send request to %s: %s", requestURL, err)
}
defer func() {
_ = resp.Body.Close()
}()
if resp.StatusCode != 200 {
t.Fatalf("unexpected status code received from %s; got %d; want 200", requestURL, resp.StatusCode)
}
data, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("cannot read response from %s: %s", requestURL, err)
}
return data
}
func checkMetricsResult(got, want []Metric) error {
for _, r := range append([]Metric(nil), got...) {
want = removeIfFoundMetrics(r, want)
}
if len(want) > 0 {
return fmt.Errorf("expected metrics %+v not found in %+v", want, got)
}
return nil
}
func removeIfFoundMetrics(r Metric, contains []Metric) []Metric {
for i, item := range contains {
if reflect.DeepEqual(r.Metric, item.Metric) && reflect.DeepEqual(r.Values, item.Values) &&
reflect.DeepEqual(r.Timestamps, item.Timestamps) {
contains[i] = contains[len(contains)-1]
return contains[:len(contains)-1]
}
}
return contains
}
func checkSeriesResult(got, want Series) error {
if got.Status != want.Status {
return fmt.Errorf("status mismatch %q - %q", want.Status, got.Status)
}
wantData := append([]map[string]string(nil), want.Data...)
for _, r := range got.Data {
wantData = removeIfFoundSeries(r, wantData)
}
if len(wantData) > 0 {
return fmt.Errorf("expected seria(s) %+v not found in %+v", wantData, got.Data)
}
return nil
}
func removeIfFoundSeries(r map[string]string, contains []map[string]string) []map[string]string {
for i, item := range contains {
if reflect.DeepEqual(r, item) {
contains[i] = contains[len(contains)-1]
return contains[:len(contains)-1]
}
}
return contains
}
func TestImportJSONLines(t *testing.T) {
f := func(labelsCount, labelLen int) {
t.Helper()
reqURL := fmt.Sprintf("http://localhost%s/api/v1/import", testHTTPListenAddr)
line := generateJSONLine(labelsCount, labelLen)
req, err := http.NewRequest("POST", reqURL, bytes.NewBufferString(line))
if err != nil {
t.Fatalf("cannot create request: %s", err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("cannot perform request for labelsCount=%d, labelLen=%d: %s", labelsCount, labelLen, err)
}
if resp.StatusCode != 204 {
t.Fatalf("unexpected statusCode for labelsCount=%d, labelLen=%d; got %d; want 204", labelsCount, labelLen, resp.StatusCode)
}
}
// labels with various lengths
for i := 0; i < 500; i++ {
f(10, i*5)
}
// Too many labels
f(1000, 100)
// Too long labels
f(1, 100_000)
f(10, 100_000)
f(10, 10_000)
}
func generateJSONLine(labelsCount, labelLen int) string {
m := make(map[string]string, labelsCount)
m["__name__"] = generateSizedRandomString(labelLen)
for j := 1; j < labelsCount; j++ {
labelName := generateSizedRandomString(labelLen)
labelValue := generateSizedRandomString(labelLen)
m[labelName] = labelValue
}
type jsonLine struct {
Metric map[string]string `json:"metric"`
Values []float64 `json:"values"`
Timestamps []int64 `json:"timestamps"`
}
line := &jsonLine{
Metric: m,
Values: []float64{1.34},
Timestamps: []int64{time.Now().UnixNano() / 1e6},
}
data, err := json.Marshal(&line)
if err != nil {
panic(fmt.Errorf("cannot marshal JSON: %w", err))
}
data = append(data, '\n')
return string(data)
}
const alphabetSample = `qwertyuiopasdfghjklzxcvbnm`
func generateSizedRandomString(size int) string {
dst := make([]byte, size)
for i := range dst {
dst[i] = alphabetSample[rand.Intn(len(alphabetSample))]
}
return string(dst)
}

View File

@@ -9,4 +9,5 @@ COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certifica
EXPOSE 8428
ENTRYPOINT ["/victoria-metrics-prod"]
ARG TARGETARCH
COPY victoria-metrics-linux-${TARGETARCH}-prod ./victoria-metrics-prod
ARG BINARY_SUFFIX=non-existing
COPY victoria-metrics-linux-${TARGETARCH}-prod${BINARY_SUFFIX} ./victoria-metrics-prod

View File

@@ -10,7 +10,7 @@ import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/decimal"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompb"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/prometheus"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/storage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/timeserieslimits"
@@ -49,7 +49,7 @@ func selfScraper(scrapeInterval time.Duration) {
var bb bytesutil.ByteBuffer
var rows prometheus.Rows
var mrs []storage.MetricRow
var labels []prompbmarshal.Label
var labels []prompb.Label
t := time.NewTicker(scrapeInterval)
f := func(currentTime time.Time, sendStaleMarkers bool) {
currentTimestamp := currentTime.UnixNano() / 1e6
@@ -57,7 +57,8 @@ func selfScraper(scrapeInterval time.Duration) {
appmetrics.WritePrometheusMetrics(&bb)
s := bytesutil.ToUnsafeString(bb.B)
rows.Reset()
rows.Unmarshal(s)
// VictoriaMetrics components don't expose metadata yet, only need to parse samples
rows.UnmarshalWithErrLogger(s, nil)
mrs = mrs[:0]
for i := range rows.Rows {
r := &rows.Rows[i]
@@ -104,11 +105,11 @@ func selfScraper(scrapeInterval time.Duration) {
}
}
func addLabel(dst []prompbmarshal.Label, key, value string) []prompbmarshal.Label {
func addLabel(dst []prompb.Label, key, value string) []prompb.Label {
if len(dst) < cap(dst) {
dst = dst[:len(dst)+1]
} else {
dst = append(dst, prompbmarshal.Label{})
dst = append(dst, prompb.Label{})
}
lb := &dst[len(dst)-1]
lb.Name = key

View File

@@ -1,14 +0,0 @@
{
"name": "csv export",
"data": [
"rfc3339,4,{TIME_MS}",
"rfc3339milli,6,{TIME_MS}",
"ts,8,{TIME_MS}",
"tsms,10,{TIME_MS},"
],
"insert_query": "?format=1:label:tfmt,2:metric:test_csv,3:time:unix_ms",
"query": [
"/api/v1/export/csv?format=__name__,tfmt,__value__,__timestamp__:rfc3339&match[]={__name__=\"test_csv\"}&step=30s&start={TIME_MS-180s}"
],
"expected_result_lines_count": 4
}

View File

@@ -1,14 +0,0 @@
{
"name": "csv export with extra_labels",
"data": [
"location-1,4,{TIME_MS}",
"location-2,6,{TIME_MS}",
"location-3,8,{TIME_MS}",
"location-4,10,{TIME_MS},"
],
"insert_query": "?format=1:label:location,2:metric:test_csv_labels,3:time:unix_ms&extra_label=location=location-1",
"query": [
"/api/v1/export/csv?format=__name__,location,__value__,__timestamp__:unix_ms&match[]={__name__=\"test_csv\"}&step=30s&start={TIME_MS-180s}"
],
"expected_result_lines_count": 4
}

View File

@@ -1,8 +0,0 @@
{
"name": "basic_insertion",
"data": ["graphite.foo.bar.baz;tag1=value1;tag2=value2 123 {TIME_S}"],
"query": ["/api/v1/export?match={__name__!=''}"],
"result_metrics": [
{"metric":{"__name__":"graphite.foo.bar.baz","tag1":"value1","tag2":"value2"},"values":[123], "timestamps": ["{TIME_MSZ}"]}
]
}

View File

@@ -1,16 +0,0 @@
{
"name": "comparison-not-inf-not-nan",
"issue": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/150",
"data": [
"not_nan_not_inf;item=x 1 {TIME_S-1m}",
"not_nan_not_inf;item=x 1 {TIME_S-2m}",
"not_nan_not_inf;item=y 3 {TIME_S-1m}",
"not_nan_not_inf;item=y 1 {TIME_S-2m}"],
"query": ["/api/v1/query_range?query=1/(not_nan_not_inf-1)!=inf!=nan&start={TIME_S-3m}&end={TIME_S}&step=60"],
"result_query": {
"status":"success",
"data":{"resultType":"matrix",
"result":[
{"metric":{"item":"y"},"values":[["{TIME_S-1m}","0.5"], ["{TIME_S}","0.5"]]}
]}}
}

View File

@@ -1,16 +0,0 @@
{
"name": "empty-label-match",
"issue": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/395",
"data": [
"empty_label_match 1 {TIME_S-1m}",
"empty_label_match;foo=bar 2 {TIME_S-1m}",
"empty_label_match;foo=baz 3 {TIME_S-1m}"],
"query": ["/api/v1/query_range?query=empty_label_match{foo=~'bar|'}&start={TIME_S-1m}&end={TIME_S}&step=60"],
"result_query": {
"status":"success",
"data":{"resultType":"matrix",
"result":[
{"metric":{"__name__":"empty_label_match"},"values":[["{TIME_S-1m}","1"],["{TIME_S}","1"]]},
{"metric":{"__name__":"empty_label_match","foo":"bar"},"values":[["{TIME_S-1m}","2"],["{TIME_S}","2"]]}
]}}
}

View File

@@ -1,17 +0,0 @@
{
"name": "graphite-selector",
"issue": "",
"data": [
"graphite-selector.bar.baz 1 {TIME_S-1m}",
"graphite-selector.xxx.yy 2 {TIME_S-1m}",
"graphite-selector.bb.cc 3 {TIME_S-1m}",
"graphite-selector.a.baz 4 {TIME_S-1m}"],
"query": ["/api/v1/query?query=sort({__graphite__='graphite-selector.*.baz'})&time={TIME_S-1m}"],
"result_query": {
"status":"success",
"data":{"resultType":"vector","result":[
{"metric":{"__name__":"graphite-selector.bar.baz"},"value":["{TIME_S-1m}","1"]},
{"metric":{"__name__":"graphite-selector.a.baz"},"value":["{TIME_S-1m}","4"]}
]}
}
}

View File

@@ -1,23 +0,0 @@
{
"name": "max_lookback_set",
"issue": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/209",
"data": [
"max_lookback_set 1 {TIME_S-30s}",
"max_lookback_set 2 {TIME_S-60s}",
"max_lookback_set 3 {TIME_S-120s}",
"max_lookback_set 4 {TIME_S-150s}"
],
"query": ["/api/v1/query_range?query=max_lookback_set&start={TIME_S-150s}&end={TIME_S}&step=10s&max_lookback=1s"],
"result_query": {
"status":"success",
"data":{"resultType":"matrix",
"result":[{"metric":{"__name__":"max_lookback_set"},"values":[
["{TIME_S-150s}","4"],
["{TIME_S-120s}","3"],
["{TIME_S-60s}","2"],
["{TIME_S-30s}","1"],
["{TIME_S-20s}","1"],
["{TIME_S-10s}","1"],
["{TIME_S-0s}","1"]
]}]}}
}

View File

@@ -1,31 +0,0 @@
{
"name": "max_lookback_unset",
"issue": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/209",
"data": [
"max_lookback_unset 1 {TIME_S-30s}",
"max_lookback_unset 2 {TIME_S-60s}",
"max_lookback_unset 3 {TIME_S-120s}",
"max_lookback_unset 4 {TIME_S-150s}"
],
"query": ["/api/v1/query_range?query=max_lookback_unset&start={TIME_S-150s}&end={TIME_S}&step=10s"],
"result_query": {
"status":"success",
"data":{"resultType":"matrix",
"result":[{"metric":{"__name__":"max_lookback_unset"},"values":[
["{TIME_S-150s}","4"],
["{TIME_S-140s}","4"],
["{TIME_S-130s}","4"],
["{TIME_S-120s}","3"],
["{TIME_S-110s}","3"],
["{TIME_S-100s}","3"],
["{TIME_S-90s}","3"],
["{TIME_S-80s}","3"],
["{TIME_S-60s}","2"],
["{TIME_S-50s}","2"],
["{TIME_S-40s}","2"],
["{TIME_S-30s}","1"],
["{TIME_S-20s}","1"],
["{TIME_S-10s}","1"],
["{TIME_S-0s}","1"]
]}]}}
}

View File

@@ -1,16 +0,0 @@
{
"name": "name-plus-negative-filter",
"issue": "",
"data": [
"name-plus-negative-filter;foo=123 1 {TIME_S-1m}",
"name-plus-negative-filter;bar=123 2 {TIME_S-1m}",
"name-plus-negative-filter;foo=qwe 3 {TIME_S-1m}"
],
"query": ["/api/v1/query?query={__name__='name-plus-negative-filter',foo!='123'}&time={TIME_S-1m}"],
"result_query": {
"status":"success",
"data":{"resultType":"vector","result":[
{"metric":{"__name__":"name-plus-negative-filter","foo":"qwe"},"value":["{TIME_S-1m}","3"]}
]}
}
}

View File

@@ -1,18 +0,0 @@
{
"name": "not-nan-as-missing-data",
"issue": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/153",
"data": [
"not_nan_as_missing_data;item=x 2 {TIME_S-2m}",
"not_nan_as_missing_data;item=x 1 {TIME_S-1m}",
"not_nan_as_missing_data;item=y 4 {TIME_S-2m}",
"not_nan_as_missing_data;item=y 3 {TIME_S-1m}"
],
"query": ["/api/v1/query_range?query=not_nan_as_missing_data>1&start={TIME_S-2m}&end={TIME_S}&step=60"],
"result_query": {
"status":"success",
"data":{"resultType":"matrix",
"result":[
{"metric":{"__name__":"not_nan_as_missing_data","item":"x"},"values":[["{TIME_S-2m}","2"]]},
{"metric":{"__name__":"not_nan_as_missing_data","item":"y"},"values":[["{TIME_S-2m}","4"],["{TIME_S-1m}","3"],["{TIME_S}", "3"]]}
]}}
}

View File

@@ -1,14 +0,0 @@
{
"name": "subquery-aggregation",
"issue": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/184",
"data": [
"forms_daily_count;item=x 1 {TIME_S-59s}",
"forms_daily_count;item=x 2 {TIME_S-1m59s}",
"forms_daily_count;item=y 3 {TIME_S-59s}",
"forms_daily_count;item=y 4 {TIME_S-1m59s}"],
"query": ["/api/v1/query?query=min%20by%20(item)%20(min_over_time(forms_daily_count[10m:1m]))&time={TIME_S-1m}&latency_offset=1ms"],
"result_query": {
"status":"success",
"data":{"resultType":"vector","result":[{"metric":{"item":"x"},"value":["{TIME_S-1m}","2"]},{"metric":{"item":"y"},"value":["{TIME_S-1m}","4"]}]}
}
}

View File

@@ -1,9 +0,0 @@
{
"name": "basic_insertion",
"data": ["measurement,tag1=value1,tag2=value2 field1=1.23,field2=123 {TIME_NS}"],
"query": ["/api/v1/export?match={__name__!=''}"],
"result_metrics": [
{"metric":{"__name__":"measurement_field2","tag1":"value1","tag2":"value2"},"values":[123], "timestamps": ["{TIME_MS}"]},
{"metric":{"__name__":"measurement_field1","tag1":"value1","tag2":"value2"},"values":[1.23], "timestamps": ["{TIME_MS}"]}
]
}

View File

@@ -1,10 +0,0 @@
{
"name": "insert_with_extra_labels",
"data": ["measurement,tag1=value1,tag2=value2 field6=1.23,field5=123 {TIME_NS}"],
"insert_query": "?extra_label=job=test&extra_label=tag2=value10",
"query": ["/api/v1/export?match={__name__!=''}"],
"result_metrics": [
{"metric":{"__name__":"measurement_field5","tag1":"value1","job": "test","tag2":"value10"},"values":[123], "timestamps": ["{TIME_MS}"]},
{"metric":{"__name__":"measurement_field6","tag1":"value1","job": "test","tag2":"value10"},"values":[1.23], "timestamps": ["{TIME_MS}"]}
]
}

View File

@@ -1,8 +0,0 @@
{
"name": "basic_insertion",
"data": ["put openstdb.foo.bar.baz {TIME_S} 123 tag1=value1 tag2=value2"],
"query": ["/api/v1/export?match={__name__!=''}"],
"result_metrics": [
{"metric":{"__name__":"openstdb.foo.bar.baz","tag1":"value1","tag2":"value2"},"values":[123], "timestamps": ["{TIME_MSZ}"]}
]
}

View File

@@ -1,8 +0,0 @@
{
"name": "basic_insertion",
"data": ["{\"metric\": \"opentsdbhttp.foo\", \"value\": 1001, \"timestamp\": {TIME_S}, \"tags\": {\"bar\":\"baz\", \"x\": \"y\"}}"],
"query": ["/api/v1/export?match={__name__!=''}"],
"result_metrics": [
{"metric":{"__name__":"opentsdbhttp.foo","bar":"baz","x":"y"},"values":[1001], "timestamps": ["{TIME_MSZ}"]}
]
}

View File

@@ -1,9 +0,0 @@
{
"name": "multiline",
"data": ["[{\"metric\": \"opentsdbhttp.multiline1\", \"value\": 1001, \"timestamp\": \"{TIME_S}\", \"tags\": {\"bar\":\"baz\", \"x\": \"y\"}}, {\"metric\": \"opentsdbhttp.multiline2\", \"value\": 1002, \"timestamp\": {TIME_S}}]"],
"query": ["/api/v1/export?match={__name__!=''}"],
"result_metrics": [
{"metric":{"__name__":"opentsdbhttp.multiline1","bar":"baz","x":"y"},"values":[1001], "timestamps": ["{TIME_MSZ}"]},
{"metric":{"__name__":"opentsdbhttp.multiline2"},"values":[1002], "timestamps": ["{TIME_MSZ}"]}
]
}

View File

@@ -1,9 +0,0 @@
{
"name": "insert_with_extra_labels",
"data": ["{\"metric\": \"opentsdbhttp.foobar\", \"value\": 1001, \"timestamp\": {TIME_S}, \"tags\": {\"bar\":\"baz\", \"x\": \"y\"}}"],
"insert_query": "?extra_label=job=open-test&extra_label=x=z",
"query": ["/api/v1/export?match={__name__!=''}"],
"result_metrics": [
{"metric":{"__name__":"opentsdbhttp.foobar","bar":"baz","x":"z","job": "open-test"},"values":[1001], "timestamps": ["{TIME_MSZ}"]}
]
}

View File

@@ -1,8 +0,0 @@
{
"name": "basic_insertion",
"data": ["[{\"labels\":[{\"name\":\"__name__\",\"value\":\"prometheus.bar\"},{\"name\":\"baz\",\"value\":\"qux\"}],\"samples\":[{\"value\":100000,\"timestamp\":\"{TIME_MS}\"}]}]"],
"query": ["/api/v1/export?match={__name__!=''}"],
"result_metrics": [
{"metric":{"__name__":"prometheus.bar","baz":"qux"},"values":[100000], "timestamps": ["{TIME_MS}"]}
]
}

View File

@@ -1,10 +0,0 @@
{
"name": "case-sensitive-regex",
"issue": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/161",
"data": ["[{\"labels\":[{\"name\":\"__name__\",\"value\":\"prometheus.sensitiveRegex\"},{\"name\":\"label\",\"value\":\"sensitiveRegex\"}],\"samples\":[{\"value\":2,\"timestamp\":\"{TIME_MS}\"}]},{\"labels\":[{\"name\":\"__name__\",\"value\":\"prometheus.sensitiveRegex\"},{\"name\":\"label\",\"value\":\"SensitiveRegex\"}],\"samples\":[{\"value\":1,\"timestamp\":\"{TIME_MS}\"}]}]"],
"query": ["/api/v1/export?match={label=~'(?i)sensitiveregex'}"],
"result_metrics": [
{"metric":{"__name__":"prometheus.sensitiveRegex","label":"sensitiveRegex"},"values":[2], "timestamps": ["{TIME_MS}"]},
{"metric":{"__name__":"prometheus.sensitiveRegex","label":"SensitiveRegex"},"values":[1], "timestamps": ["{TIME_MS}"]}
]
}

View File

@@ -1,9 +0,0 @@
{
"name": "duplicate_label",
"issue": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/172",
"data": ["[{\"labels\":[{\"name\":\"__name__\",\"value\":\"prometheus.duplicate_label\"},{\"name\":\"duplicate\",\"value\":\"label\"},{\"name\":\"duplicate\",\"value\":\"label\"}],\"samples\":[{\"value\":1,\"timestamp\":\"{TIME_MS}\"}]}]"],
"query": ["/api/v1/export?match={__name__!=''}"],
"result_metrics": [
{"metric":{"__name__":"prometheus.duplicate_label","duplicate":"label"},"values":[1], "timestamps": ["{TIME_MS}"]}
]
}

View File

@@ -1,12 +0,0 @@
{
"name": "instant query with look-behind window",
"data": ["[{\"labels\":[{\"name\":\"__name__\",\"value\":\"foo\"}],\"samples\":[{\"value\":1,\"timestamp\":\"{TIME_MS-60s}\"}]}]"],
"query": ["/api/v1/query?query=foo[5m]"],
"result_query": {
"status": "success",
"data":{
"resultType":"matrix",
"result":[{"metric":{"__name__":"foo"},"values":[["{TIME_S-60s}", "1"]]}]
}
}
}

View File

@@ -1,11 +0,0 @@
{
"name": "instant scalar query",
"query": ["/api/v1/query?query=42&time={TIME_S}"],
"result_query": {
"status": "success",
"data":{
"resultType":"vector",
"result":[{"metric":{},"value":["{TIME_S}", "42"]}]
}
}
}

View File

@@ -1,13 +0,0 @@
{
"name": "too big look-behind window",
"issue": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5553",
"data": ["[{\"labels\":[{\"name\":\"__name__\",\"value\":\"foo\"},{\"name\":\"issue\",\"value\":\"5553\"}],\"samples\":[{\"value\":1,\"timestamp\":\"{TIME_MS-60s}\"}]}]"],
"query": ["/api/v1/query?query=foo{issue=\"5553\"}[100y]"],
"result_query": {
"status": "success",
"data":{
"resultType":"matrix",
"result":[{"metric":{"__name__":"foo", "issue": "5553"},"values":[["{TIME_S-60s}", "1"]]}]
}
}
}

View File

@@ -1,15 +0,0 @@
{
"name": "match_series",
"issue": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/155",
"data": ["[{\"labels\":[{\"name\":\"__name__\",\"value\":\"MatchSeries\"},{\"name\":\"db\",\"value\":\"TenMinute\"},{\"name\":\"TurbineType\",\"value\":\"V112\"},{\"name\":\"Park\",\"value\":\"1\"}],\"samples\":[{\"value\":1,\"timestamp\":\"{TIME_MS}\"}]},{\"labels\":[{\"name\":\"__name__\",\"value\":\"MatchSeries\"},{\"name\":\"db\",\"value\":\"TenMinute\"},{\"name\":\"TurbineType\",\"value\":\"V112\"},{\"name\":\"Park\",\"value\":\"2\"}],\"samples\":[{\"value\":1,\"timestamp\":\"{TIME_MS}\"}]},{\"labels\":[{\"name\":\"__name__\",\"value\":\"MatchSeries\"},{\"name\":\"db\",\"value\":\"TenMinute\"},{\"name\":\"TurbineType\",\"value\":\"V112\"},{\"name\":\"Park\",\"value\":\"3\"}],\"samples\":[{\"value\":1,\"timestamp\":\"{TIME_MS}\"}]},{\"labels\":[{\"name\":\"__name__\",\"value\":\"MatchSeries\"},{\"name\":\"db\",\"value\":\"TenMinute\"},{\"name\":\"TurbineType\",\"value\":\"V112\"},{\"name\":\"Park\",\"value\":\"4\"}],\"samples\":[{\"value\":1,\"timestamp\":\"{TIME_MS}\"}]}]"],
"query": ["/api/v1/series?match[]={__name__='MatchSeries'}", "/api/v1/series?match[]={__name__=~'MatchSeries.*'}"],
"result_series": {
"status": "success",
"data": [
{"__name__":"MatchSeries","db":"TenMinute","Park":"1","TurbineType":"V112"},
{"__name__":"MatchSeries","db":"TenMinute","Park":"2","TurbineType":"V112"},
{"__name__":"MatchSeries","db":"TenMinute","Park":"3","TurbineType":"V112"},
{"__name__":"MatchSeries","db":"TenMinute","Park":"4","TurbineType":"V112"}
]
}
}

View File

@@ -1,18 +0,0 @@
{
"name": "query range",
"issue": "https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5553",
"data": ["[{\"labels\":[{\"name\":\"__name__\",\"value\":\"bar\"}],\"samples\":[{\"value\":1,\"timestamp\":\"{TIME_MS-60s}\"}, {\"value\":2,\"timestamp\":\"{TIME_MS-120s}\"}, {\"value\":1,\"timestamp\":\"{TIME_MS-180s}\"}]}]"],
"query": ["/api/v1/query_range?query=bar&step=30s&start={TIME_MS-180s}"],
"result_query": {
"status": "success",
"data":{
"resultType":"matrix",
"result":[
{
"metric":{"__name__":"bar"},
"values":[["{TIME_S-180s}", "1"],["{TIME_S-150s}", "1"],["{TIME_S-120s}", "2"],["{TIME_S-90s}", "2"], ["{TIME_S-60s}", "1"], ["{TIME_S-30s}", "1"], ["{TIME_S}", "1"]]
}
]
}
}
}

View File

@@ -1,9 +0,0 @@
{
"name": "basic_insertion_with_extra_labels",
"insert_query": "?extra_label=job=prom-test&extra_label=baz=bar",
"data": ["[{\"labels\":[{\"name\":\"__name__\",\"value\":\"prometheus.foobar\"},{\"name\":\"baz\",\"value\":\"qux\"}],\"samples\":[{\"value\":100000,\"timestamp\":\"{TIME_MS}\"}]}]"],
"query": ["/api/v1/export?match={__name__!=''}"],
"result_metrics": [
{"metric":{"__name__":"prometheus.foobar","baz":"bar","job": "prom-test"},"values":[100000], "timestamps": ["{TIME_MS}"]}
]
}

View File

@@ -1,8 +0,0 @@
{
"name": "basic_select_with_extra_labels",
"data": ["[{\"labels\":[{\"name\":\"__name__\",\"value\":\"prometheus.tenant.limits\"},{\"name\":\"baz\",\"value\":\"qux\"},{\"name\":\"tenant\",\"value\":\"dev\"}],\"samples\":[{\"value\":100000,\"timestamp\":\"{TIME_MS}\"}]},{\"labels\":[{\"name\":\"__name__\",\"value\":\"prometheus.up\"},{\"name\":\"baz\",\"value\":\"qux\"}],\"samples\":[{\"value\":100000,\"timestamp\":\"{TIME_MS}\"}]}]"],
"query": ["/api/v1/export?match={__name__!=''}&extra_label=tenant=dev"],
"result_metrics": [
{"metric":{"__name__":"prometheus.tenant.limits","baz":"qux","tenant": "dev"},"values":[100000], "timestamps": ["{TIME_MS}"]}
]
}

1
app/vlagent/README.md Normal file
View File

@@ -0,0 +1 @@
VictoriaLogs source code has been moved to [github.com/VictoriaMetrics/VictoriaLogs](https://github.com/VictoriaMetrics/VictoriaLogs/).

1
app/vlinsert/README.md Normal file
View File

@@ -0,0 +1 @@
VictoriaLogs source code has been moved to [github.com/VictoriaMetrics/VictoriaLogs](https://github.com/VictoriaMetrics/VictoriaLogs/).

View File

@@ -1,260 +0,0 @@
package datadog
import (
"bytes"
"fmt"
"net/http"
"strconv"
"time"
"github.com/VictoriaMetrics/metrics"
"github.com/valyala/fastjson"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/protoparserutil"
)
var (
datadogStreamFields = flagutil.NewArrayString("datadog.streamFields", "Comma-separated list of fields to use as log stream fields for logs ingested via DataDog protocol. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/datadog-agent/#stream-fields")
datadogIgnoreFields = flagutil.NewArrayString("datadog.ignoreFields", "Comma-separated list of fields to ignore for logs ingested via DataDog protocol. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/datadog-agent/#dropping-fields")
maxRequestSize = flagutil.NewBytes("datadog.maxRequestSize", 64*1024*1024, "The maximum size in bytes of a single DataDog request")
)
var parserPool fastjson.ParserPool
// RequestHandler processes Datadog insert requests
func RequestHandler(path string, w http.ResponseWriter, r *http.Request) bool {
switch path {
case "/api/v1/validate":
fmt.Fprintf(w, `{}`)
return true
case "/api/v2/logs":
return datadogLogsIngestion(w, r)
default:
return false
}
}
func datadogLogsIngestion(w http.ResponseWriter, r *http.Request) bool {
w.Header().Add("Content-Type", "application/json")
startTime := time.Now()
v2LogsRequestsTotal.Inc()
var ts int64
if tsValue := r.Header.Get("dd-message-timestamp"); tsValue != "" && tsValue != "0" {
var err error
ts, err = strconv.ParseInt(tsValue, 10, 64)
if err != nil {
httpserver.Errorf(w, r, "could not parse dd-message-timestamp header value: %s", err)
return true
}
ts *= 1e6
} else {
ts = startTime.UnixNano()
}
cp, err := insertutil.GetCommonParams(r)
if err != nil {
httpserver.Errorf(w, r, "%s", err)
return true
}
if len(cp.StreamFields) == 0 {
cp.StreamFields = *datadogStreamFields
}
if len(cp.IgnoreFields) == 0 {
cp.IgnoreFields = *datadogIgnoreFields
}
if err := vlstorage.CanWriteData(); err != nil {
httpserver.Errorf(w, r, "%s", err)
return true
}
encoding := r.Header.Get("Content-Encoding")
err = protoparserutil.ReadUncompressedData(r.Body, encoding, maxRequestSize, func(data []byte) error {
lmp := cp.NewLogMessageProcessor("datadog", false)
err := readLogsRequest(ts, data, lmp)
lmp.MustClose()
return err
})
if err != nil {
httpserver.Errorf(w, r, "cannot read DataDog protocol data: %s", err)
return true
}
// update v2LogsRequestDuration only for successfully parsed requests
// There is no need in updating v2LogsRequestDuration for request errors,
// since their timings are usually much smaller than the timing for successful request parsing.
v2LogsRequestDuration.UpdateDuration(startTime)
fmt.Fprintf(w, `{}`)
return true
}
var (
v2LogsRequestsTotal = metrics.NewCounter(`vl_http_requests_total{path="/insert/datadog/api/v2/logs"}`)
v2LogsRequestDuration = metrics.NewHistogram(`vl_http_request_duration_seconds{path="/insert/datadog/api/v2/logs"}`)
)
// datadog message field has two formats:
// - regular log message with string text
// - nested json format for serverless plugins
// which has the following format:
// {"message": {"message": "text","lamdba": {"arn": "string","requestID": "string"}, "timestamp": int64} }
//
// See https://github.com/DataDog/datadog-lambda-extension/blob/28b90c7e4e985b72d60b5f5a5147c69c7ac693c4/bottlecap/src/logs/lambda/mod.rs#L24
func appendMsgFields(fields []logstorage.Field, v *fastjson.Value) ([]logstorage.Field, error) {
switch v.Type() {
case fastjson.TypeString:
val := v.GetStringBytes()
fields = append(fields, logstorage.Field{
Name: "_msg",
Value: bytesutil.ToUnsafeString(val),
})
case fastjson.TypeObject:
var firstErr error
v.GetObject().Visit(func(k []byte, v *fastjson.Value) {
if firstErr != nil {
return
}
switch bytesutil.ToUnsafeString(k) {
case "message":
val := v.GetStringBytes()
fields = append(fields, logstorage.Field{
Name: "_msg",
Value: bytesutil.ToUnsafeString(val),
})
case "status":
val := v.GetStringBytes()
fields = append(fields, logstorage.Field{
Name: "status",
Value: bytesutil.ToUnsafeString(val),
})
case "lamdba":
obj, err := v.Object()
if err != nil {
firstErr = err
firstErr = fmt.Errorf("unexpected lambda value type for %q:%q; want object", k, v)
return
}
obj.Visit(func(k []byte, v *fastjson.Value) {
if firstErr != nil {
return
}
val, err := v.StringBytes()
if err != nil {
firstErr = fmt.Errorf("unexpected lambda label value type for %q:%q; want string", k, v)
return
}
fields = append(fields, logstorage.Field{
Name: bytesutil.ToUnsafeString(k),
Value: bytesutil.ToUnsafeString(val),
})
})
}
})
default:
return fields, fmt.Errorf("unsupported message type %q", v.Type().String())
}
return fields, nil
}
// readLogsRequest parses data according to DataDog logs format
// https://docs.datadoghq.com/api/latest/logs/#send-logs
func readLogsRequest(ts int64, data []byte, lmp insertutil.LogMessageProcessor) error {
p := parserPool.Get()
defer parserPool.Put(p)
v, err := p.ParseBytes(data)
if err != nil {
return fmt.Errorf("cannot parse JSON request body: %w", err)
}
records, err := v.Array()
if err != nil {
return fmt.Errorf("cannot extract array from parsed JSON: %w", err)
}
var fields []logstorage.Field
for _, r := range records {
o, err := r.Object()
if err != nil {
return fmt.Errorf("could not extract log record: %w", err)
}
o.Visit(func(k []byte, v *fastjson.Value) {
if err != nil {
return
}
switch bytesutil.ToUnsafeString(k) {
case "message":
fields, err = appendMsgFields(fields, v)
if err != nil {
return
}
case "timestamp":
val, e := v.Int64()
if e != nil {
err = fmt.Errorf("failed to parse timestamp for %q:%q", k, v)
}
if val > 0 {
ts = val * 1e6
}
case "ddtags":
// https://docs.datadoghq.com/getting_started/tagging/
val, e := v.StringBytes()
if e != nil {
err = fmt.Errorf("unexpected label value type for %q:%q; want string", k, v)
return
}
var pair []byte
idx := 0
for idx >= 0 {
idx = bytes.IndexByte(val, ',')
if idx < 0 {
pair = val
} else {
pair = val[:idx]
val = val[idx+1:]
}
if len(pair) > 0 {
n := bytes.IndexByte(pair, ':')
if n < 0 {
// No tag value.
fields = append(fields, logstorage.Field{
Name: bytesutil.ToUnsafeString(pair),
Value: "no_label_value",
})
}
fields = append(fields, logstorage.Field{
Name: bytesutil.ToUnsafeString(pair[:n]),
Value: bytesutil.ToUnsafeString(pair[n+1:]),
})
}
}
default:
val, e := v.StringBytes()
if e != nil {
err = fmt.Errorf("unexpected label value type for %q:%q; want string", k, v)
return
}
fields = append(fields, logstorage.Field{
Name: bytesutil.ToUnsafeString(k),
Value: bytesutil.ToUnsafeString(val),
})
}
})
if err != nil {
return err
}
lmp.AddRow(ts, fields, nil)
fields = fields[:0]
}
return nil
}

View File

@@ -1,104 +0,0 @@
package datadog
import (
"testing"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
)
func TestReadLogsRequestFailure(t *testing.T) {
f := func(data string) {
t.Helper()
ts := time.Now().UnixNano()
lmp := &insertutil.TestLogMessageProcessor{}
if err := readLogsRequest(ts, []byte(data), lmp); err == nil {
t.Fatalf("expecting non-empty error")
}
if err := lmp.Verify(nil, ""); err != nil {
t.Fatalf("unexpected error: %s", err)
}
}
f("foobar")
f(`{}`)
f(`["create":{}]`)
f(`{"create":{}}
foobar`)
}
func TestReadLogsRequestSuccess(t *testing.T) {
f := func(data string, rowsExpected int, resultExpected string) {
t.Helper()
ts := time.Now().UnixNano()
var timestampsExpected []int64
for i := 0; i < rowsExpected; i++ {
timestampsExpected = append(timestampsExpected, ts)
}
lmp := &insertutil.TestLogMessageProcessor{}
if err := readLogsRequest(ts, []byte(data), lmp); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if err := lmp.Verify(timestampsExpected, resultExpected); err != nil {
t.Fatalf("unexpected error: %s", err)
}
}
// Verify non-empty data
data := `[
{
"ddsource":"nginx",
"ddtags":"tag1:value1,tag2:value2",
"hostname":"127.0.0.1",
"message":"bar",
"service":"test"
}, {
"ddsource":"nginx",
"ddtags":"tag1:value1,tag2:value2",
"hostname":"127.0.0.1",
"message":{"message": "nested"},
"service":"test"
}, {
"ddsource":"nginx",
"ddtags":"tag1:value1,tag2:value2",
"hostname":"127.0.0.1",
"message":"foobar",
"service":"test"
}, {
"ddsource":"nginx",
"ddtags":"tag1:value1,tag2:value2",
"hostname":"127.0.0.1",
"message":"baz",
"service":"test"
}, {
"ddsource":"nginx",
"ddtags":"tag1:value1,tag2:value2",
"hostname":"127.0.0.1",
"message":"xyz",
"service":"test"
}, {
"ddsource": "nginx",
"ddtags":"tag1:value1,tag2:value2,",
"hostname":"127.0.0.1",
"message":"xyz",
"service":"test"
}, {
"ddsource":"nginx",
"ddtags":",tag1:value1,tag2:value2",
"hostname":"127.0.0.1",
"message":"xyz",
"service":"test"
}
]`
rowsExpected := 7
resultExpected := `{"ddsource":"nginx","tag1":"value1","tag2":"value2","hostname":"127.0.0.1","_msg":"bar","service":"test"}
{"ddsource":"nginx","tag1":"value1","tag2":"value2","hostname":"127.0.0.1","_msg":"nested","service":"test"}
{"ddsource":"nginx","tag1":"value1","tag2":"value2","hostname":"127.0.0.1","_msg":"foobar","service":"test"}
{"ddsource":"nginx","tag1":"value1","tag2":"value2","hostname":"127.0.0.1","_msg":"baz","service":"test"}
{"ddsource":"nginx","tag1":"value1","tag2":"value2","hostname":"127.0.0.1","_msg":"xyz","service":"test"}
{"ddsource":"nginx","tag1":"value1","tag2":"value2","hostname":"127.0.0.1","_msg":"xyz","service":"test"}
{"ddsource":"nginx","tag1":"value1","tag2":"value2","hostname":"127.0.0.1","_msg":"xyz","service":"test"}`
f(data, rowsExpected, resultExpected)
}

View File

@@ -1,20 +0,0 @@
{% stripspace %}
{% func BulkResponse(n int, tookMs int64) %}
{
"took":{%dl tookMs %},
"errors":false,
"items":[
{% for i := 0; i < n; i++ %}
{
"create":{
"status":201
}
}
{% if i+1 < n %},{% endif %}
{% endfor %}
]
}
{% endfunc %}
{% endstripspace %}

View File

@@ -1,69 +0,0 @@
// Code generated by qtc from "bulk_response.qtpl". DO NOT EDIT.
// See https://github.com/valyala/quicktemplate for details.
//line app/vlinsert/elasticsearch/bulk_response.qtpl:3
package elasticsearch
//line app/vlinsert/elasticsearch/bulk_response.qtpl:3
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:3
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:3
func StreamBulkResponse(qw422016 *qt422016.Writer, n int, tookMs int64) {
//line app/vlinsert/elasticsearch/bulk_response.qtpl:3
qw422016.N().S(`{"took":`)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:5
qw422016.N().DL(tookMs)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:5
qw422016.N().S(`,"errors":false,"items":[`)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:8
for i := 0; i < n; i++ {
//line app/vlinsert/elasticsearch/bulk_response.qtpl:8
qw422016.N().S(`{"create":{"status":201}}`)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:14
if i+1 < n {
//line app/vlinsert/elasticsearch/bulk_response.qtpl:14
qw422016.N().S(`,`)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:14
}
//line app/vlinsert/elasticsearch/bulk_response.qtpl:15
}
//line app/vlinsert/elasticsearch/bulk_response.qtpl:15
qw422016.N().S(`]}`)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
}
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
func WriteBulkResponse(qq422016 qtio422016.Writer, n int, tookMs int64) {
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
StreamBulkResponse(qw422016, n, tookMs)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
qt422016.ReleaseWriter(qw422016)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
}
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
func BulkResponse(n int, tookMs int64) string {
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
qb422016 := qt422016.AcquireByteBuffer()
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
WriteBulkResponse(qb422016, n, tookMs)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
qs422016 := string(qb422016.B)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
qt422016.ReleaseByteBuffer(qb422016)
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
return qs422016
//line app/vlinsert/elasticsearch/bulk_response.qtpl:18
}

View File

@@ -1,245 +0,0 @@
package elasticsearch
import (
"flag"
"fmt"
"io"
"net/http"
"strings"
"time"
"github.com/VictoriaMetrics/metrics"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bufferedwriter"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/protoparserutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/writeconcurrencylimiter"
)
var (
elasticsearchVersion = flag.String("elasticsearch.version", "8.9.0", "Elasticsearch version to report to client")
)
// RequestHandler processes Elasticsearch insert requests
func RequestHandler(path string, w http.ResponseWriter, r *http.Request) bool {
w.Header().Add("Content-Type", "application/json")
// This header is needed for Logstash
w.Header().Set("X-Elastic-Product", "Elasticsearch")
if strings.HasPrefix(path, "/_ilm/policy") {
// Return fake response for Elasticsearch ilm request.
fmt.Fprintf(w, `{}`)
return true
}
if strings.HasPrefix(path, "/_index_template") {
// Return fake response for Elasticsearch index template request.
fmt.Fprintf(w, `{}`)
return true
}
if strings.HasPrefix(path, "/_ingest") {
// Return fake response for Elasticsearch ingest pipeline request.
// See: https://www.elastic.co/guide/en/elasticsearch/reference/8.8/put-pipeline-api.html
fmt.Fprintf(w, `{}`)
return true
}
if strings.HasPrefix(path, "/_nodes") {
// Return fake response for Elasticsearch nodes discovery request.
// See: https://www.elastic.co/guide/en/elasticsearch/reference/8.8/cluster.html
fmt.Fprintf(w, `{}`)
return true
}
if strings.HasPrefix(path, "/logstash") || strings.HasPrefix(path, "/_logstash") {
// Return fake response for Logstash APIs requests.
// See: https://www.elastic.co/guide/en/elasticsearch/reference/8.8/logstash-apis.html
fmt.Fprintf(w, `{}`)
return true
}
switch path {
case "/", "":
switch r.Method {
case http.MethodGet:
// Return fake response for Elasticsearch ping request.
// See the latest available version for Elasticsearch at https://github.com/elastic/elasticsearch/releases
fmt.Fprintf(w, `{
"version": {
"number": %q
}
}`, *elasticsearchVersion)
case http.MethodHead:
// Return empty response for Logstash ping request.
}
return true
case "/_license":
// Return fake response for Elasticsearch license request.
fmt.Fprintf(w, `{
"license": {
"uid": "cbff45e7-c553-41f7-ae4f-9205eabd80xx",
"type": "oss",
"status": "active",
"expiry_date_in_millis" : 4000000000000
}
}`)
return true
case "/_bulk":
startTime := time.Now()
bulkRequestsTotal.Inc()
cp, err := insertutil.GetCommonParams(r)
if err != nil {
httpserver.Errorf(w, r, "%s", err)
return true
}
if err := vlstorage.CanWriteData(); err != nil {
httpserver.Errorf(w, r, "%s", err)
return true
}
lmp := cp.NewLogMessageProcessor("elasticsearch_bulk", true)
encoding := r.Header.Get("Content-Encoding")
streamName := fmt.Sprintf("remoteAddr=%s, requestURI=%q", httpserver.GetQuotedRemoteAddr(r), r.RequestURI)
n, err := readBulkRequest(streamName, r.Body, encoding, cp.TimeField, cp.MsgFields, lmp)
lmp.MustClose()
if err != nil {
logger.Warnf("cannot decode log message #%d in /_bulk request: %s, stream fields: %s", n, err, cp.StreamFields)
return true
}
tookMs := time.Since(startTime).Milliseconds()
bw := bufferedwriter.Get(w)
defer bufferedwriter.Put(bw)
WriteBulkResponse(bw, n, tookMs)
_ = bw.Flush()
// update bulkRequestDuration only for successfully parsed requests
// There is no need in updating bulkRequestDuration for request errors,
// since their timings are usually much smaller than the timing for successful request parsing.
bulkRequestDuration.UpdateDuration(startTime)
return true
default:
return false
}
}
var (
bulkRequestsTotal = metrics.NewCounter(`vl_http_requests_total{path="/insert/elasticsearch/_bulk"}`)
bulkRequestDuration = metrics.NewHistogram(`vl_http_request_duration_seconds{path="/insert/elasticsearch/_bulk"}`)
)
func readBulkRequest(streamName string, r io.Reader, encoding string, timeField string, msgFields []string, lmp insertutil.LogMessageProcessor) (int, error) {
// See https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
reader, err := protoparserutil.GetUncompressedReader(r, encoding)
if err != nil {
return 0, fmt.Errorf("cannot decode Elasticsearch protocol data: %w", err)
}
defer protoparserutil.PutUncompressedReader(reader)
wcr := writeconcurrencylimiter.GetReader(reader)
defer writeconcurrencylimiter.PutReader(wcr)
lr := insertutil.NewLineReader(streamName, wcr)
n := 0
for {
ok, err := readBulkLine(lr, timeField, msgFields, lmp)
wcr.DecConcurrency()
if err != nil || !ok {
return n, err
}
n++
}
}
func readBulkLine(lr *insertutil.LineReader, timeField string, msgFields []string, lmp insertutil.LogMessageProcessor) (bool, error) {
var line []byte
// Read the command, must be "create" or "index"
for len(line) == 0 {
if !lr.NextLine() {
err := lr.Err()
return false, err
}
line = lr.Line
}
lineStr := bytesutil.ToUnsafeString(line)
if !strings.Contains(lineStr, `"create"`) && !strings.Contains(lineStr, `"index"`) {
return false, fmt.Errorf(`unexpected command %q; expecting "create" or "index"`, line)
}
// Decode log message
if !lr.NextLine() {
if err := lr.Err(); err != nil {
return false, err
}
return false, fmt.Errorf(`missing log message after the "create" or "index" command`)
}
line = lr.Line
if len(line) == 0 {
// Special case - the line could be too long, so it was skipped.
// Continue parsing next lines.
return true, nil
}
p := logstorage.GetJSONParser()
if err := p.ParseLogMessage(line); err != nil {
return false, fmt.Errorf("cannot parse json-encoded log entry: %w", err)
}
ts, err := extractTimestampFromFields(timeField, p.Fields)
if err != nil {
return false, fmt.Errorf("cannot parse timestamp: %w", err)
}
if ts == 0 {
ts = time.Now().UnixNano()
}
logstorage.RenameField(p.Fields, msgFields, "_msg")
lmp.AddRow(ts, p.Fields, nil)
logstorage.PutJSONParser(p)
return true, nil
}
func extractTimestampFromFields(timeField string, fields []logstorage.Field) (int64, error) {
for i := range fields {
f := &fields[i]
if f.Name != timeField {
continue
}
timestamp, err := parseElasticsearchTimestamp(f.Value)
if err != nil {
return 0, err
}
f.Value = ""
return timestamp, nil
}
return 0, nil
}
func parseElasticsearchTimestamp(s string) (int64, error) {
if s == "0" || s == "" {
// Special case - zero or empty timestamp must be substituted
// with the current time by the caller.
return 0, nil
}
if len(s) < len("YYYY-MM-DD") || s[len("YYYY")] != '-' {
// Try parsing timestamp in seconds or milliseconds
return insertutil.ParseUnixTimestamp(s)
}
if len(s) == len("YYYY-MM-DD") {
t, err := time.Parse("2006-01-02", s)
if err != nil {
return 0, fmt.Errorf("cannot parse date %q: %w", s, err)
}
return t.UnixNano(), nil
}
nsecs, ok := logstorage.TryParseTimestampRFC3339Nano(s)
if !ok {
return 0, fmt.Errorf("cannot parse timestamp %q", s)
}
return nsecs, nil
}

View File

@@ -1,127 +0,0 @@
package elasticsearch
import (
"bytes"
"fmt"
"github.com/golang/snappy"
"github.com/klauspost/compress/gzip"
"github.com/klauspost/compress/zlib"
"github.com/klauspost/compress/zstd"
"io"
"testing"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
)
func TestReadBulkRequest_Failure(t *testing.T) {
f := func(data string) {
t.Helper()
tlp := &insertutil.TestLogMessageProcessor{}
r := bytes.NewBufferString(data)
rows, err := readBulkRequest("test", r, "", "_time", []string{"_msg"}, tlp)
if err == nil {
t.Fatalf("expecting non-empty error")
}
if rows != 0 {
t.Fatalf("unexpected non-zero rows=%d", rows)
}
}
f("foobar")
f(`{}`)
f(`{"create":{}}`)
f(`{"creat":{}}
{}`)
f(`{"create":{}}
foobar`)
}
func TestReadBulkRequest_Success(t *testing.T) {
f := func(data, encoding, timeField, msgField string, timestampsExpected []int64, resultExpected string) {
t.Helper()
msgFields := []string{"non_existing_foo", msgField, "non_exiting_bar"}
tlp := &insertutil.TestLogMessageProcessor{}
// Read the request without compression
r := bytes.NewBufferString(data)
rows, err := readBulkRequest("test", r, "", timeField, msgFields, tlp)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if rows != len(timestampsExpected) {
t.Fatalf("unexpected rows read; got %d; want %d", rows, len(timestampsExpected))
}
if err := tlp.Verify(timestampsExpected, resultExpected); err != nil {
t.Fatal(err)
}
// Read the request with compression
tlp = &insertutil.TestLogMessageProcessor{}
if encoding != "" {
data = compressData(data, encoding)
}
r = bytes.NewBufferString(data)
rows, err = readBulkRequest("test", r, encoding, timeField, msgFields, tlp)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if rows != len(timestampsExpected) {
t.Fatalf("unexpected rows read; got %d; want %d", rows, len(timestampsExpected))
}
if err := tlp.Verify(timestampsExpected, resultExpected); err != nil {
t.Fatalf("verification failure after compression: %s", err)
}
}
// Verify an empty data
f("", "gzip", "_time", "_msg", nil, "")
f("\n", "gzip", "_time", "_msg", nil, "")
f("\n\n", "gzip", "_time", "_msg", nil, "")
// Verify non-empty data
data := `{"create":{"_index":"filebeat-8.8.0"}}
{"@timestamp":"2023-06-06T04:48:11.735Z","log":{"offset":71770,"file":{"path":"/var/log/auth.log"}},"message":"foobar"}
{"create":{"_index":"filebeat-8.8.0"}}
{"@timestamp":"2023-06-06 04:48:12.735+01:00","message":"baz"}
{"index":{"_index":"filebeat-8.8.0"}}
{"message":"xyz","@timestamp":"1686026893735","x":"y"}
{"create":{"_index":"filebeat-8.8.0"}}
{"message":"qwe rty","@timestamp":"1686026893"}
{"create":{"_index":"filebeat-8.8.0"}}
{"message":"qwe rty float","@timestamp":"1686026123.62"}
`
timeField := "@timestamp"
msgField := "message"
timestampsExpected := []int64{1686026891735000000, 1686023292735000000, 1686026893735000000, 1686026893000000000, 1686026123620000000}
resultExpected := `{"log.offset":"71770","log.file.path":"/var/log/auth.log","_msg":"foobar"}
{"_msg":"baz"}
{"_msg":"xyz","x":"y"}
{"_msg":"qwe rty"}
{"_msg":"qwe rty float"}`
f(data, "zstd", timeField, msgField, timestampsExpected, resultExpected)
}
func compressData(s string, encoding string) string {
var bb bytes.Buffer
var zw io.WriteCloser
switch encoding {
case "gzip":
zw = gzip.NewWriter(&bb)
case "zstd":
zw, _ = zstd.NewWriter(&bb)
case "snappy":
zw = snappy.NewBufferedWriter(&bb)
case "deflate":
zw = zlib.NewWriter(&bb)
default:
panic(fmt.Errorf("%q encoding is not supported", encoding))
}
if _, err := zw.Write([]byte(s)); err != nil {
panic(fmt.Errorf("unexpected error when compressing data: %w", err))
}
if err := zw.Close(); err != nil {
panic(fmt.Errorf("unexpected error when closing gzip writer: %w", err))
}
return bb.String()
}

View File

@@ -1,59 +0,0 @@
package elasticsearch
import (
"bytes"
"fmt"
"testing"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
)
func BenchmarkReadBulkRequest(b *testing.B) {
b.Run("encoding:none", func(b *testing.B) {
benchmarkReadBulkRequest(b, "")
})
b.Run("encoding:gzip", func(b *testing.B) {
benchmarkReadBulkRequest(b, "gzip")
})
b.Run("encoding:zstd", func(b *testing.B) {
benchmarkReadBulkRequest(b, "zstd")
})
b.Run("encoding:deflate", func(b *testing.B) {
benchmarkReadBulkRequest(b, "deflate")
})
b.Run("encoding:snappy", func(b *testing.B) {
benchmarkReadBulkRequest(b, "snappy")
})
}
func benchmarkReadBulkRequest(b *testing.B, encoding string) {
data := `{"create":{"_index":"filebeat-8.8.0"}}
{"@timestamp":"2023-06-06T04:48:11.735Z","log":{"offset":71770,"file":{"path":"/var/log/auth.log"}},"message":"foobar"}
{"create":{"_index":"filebeat-8.8.0"}}
{"@timestamp":"2023-06-06T04:48:12.735Z","message":"baz"}
{"create":{"_index":"filebeat-8.8.0"}}
{"message":"xyz","@timestamp":"2023-06-06T04:48:13.735Z","x":"y"}
`
if encoding != "" {
data = compressData(data, encoding)
}
dataBytes := bytesutil.ToUnsafeBytes(data)
timeField := "@timestamp"
msgFields := []string{"message"}
blp := &insertutil.BenchmarkLogMessageProcessor{}
b.ReportAllocs()
b.SetBytes(int64(len(data)))
b.RunParallel(func(pb *testing.PB) {
r := &bytes.Reader{}
for pb.Next() {
r.Reset(dataBytes)
_, err := readBulkRequest("test", r, encoding, timeField, msgFields, blp)
if err != nil {
panic(fmt.Errorf("unexpected error: %w", err))
}
}
})
}

View File

@@ -1,266 +0,0 @@
package insertutil
import (
"flag"
"fmt"
"net/http"
"strconv"
"strings"
"sync"
"time"
"github.com/VictoriaMetrics/metrics"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httputil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/timeutil"
)
var (
defaultMsgValue = flag.String("defaultMsgValue", "missing _msg field; see https://docs.victoriametrics.com/victorialogs/keyconcepts/#message-field",
"Default value for _msg field if the ingested log entry doesn't contain it; see https://docs.victoriametrics.com/victorialogs/keyconcepts/#message-field")
)
// CommonParams contains common HTTP parameters used by log ingestion APIs.
//
// See https://docs.victoriametrics.com/victorialogs/data-ingestion/#http-parameters
type CommonParams struct {
TenantID logstorage.TenantID
TimeField string
MsgFields []string
StreamFields []string
IgnoreFields []string
ExtraFields []logstorage.Field
Debug bool
DebugRequestURI string
DebugRemoteAddr string
}
// GetCommonParams returns CommonParams from r.
func GetCommonParams(r *http.Request) (*CommonParams, error) {
// Extract tenantID
tenantID, err := logstorage.GetTenantIDFromRequest(r)
if err != nil {
return nil, err
}
timeField := "_time"
if tf := httputil.GetRequestValue(r, "_time_field", "VL-Time-Field"); tf != "" {
timeField = tf
}
msgFields := httputil.GetArray(r, "_msg_field", "VL-Msg-Field")
streamFields := httputil.GetArray(r, "_stream_fields", "VL-Stream-Fields")
ignoreFields := httputil.GetArray(r, "ignore_fields", "VL-Ignore-Fields")
extraFields, err := getExtraFields(r)
if err != nil {
return nil, err
}
debug := false
if dv := httputil.GetRequestValue(r, "debug", "VL-Debug"); dv != "" {
debug, err = strconv.ParseBool(dv)
if err != nil {
return nil, fmt.Errorf("cannot parse debug=%q: %w", dv, err)
}
}
debugRequestURI := ""
debugRemoteAddr := ""
if debug {
debugRequestURI = httpserver.GetRequestURI(r)
debugRemoteAddr = httpserver.GetQuotedRemoteAddr(r)
}
cp := &CommonParams{
TenantID: tenantID,
TimeField: timeField,
MsgFields: msgFields,
StreamFields: streamFields,
IgnoreFields: ignoreFields,
ExtraFields: extraFields,
Debug: debug,
DebugRequestURI: debugRequestURI,
DebugRemoteAddr: debugRemoteAddr,
}
return cp, nil
}
func getExtraFields(r *http.Request) ([]logstorage.Field, error) {
efs := httputil.GetArray(r, "extra_fields", "VL-Extra-Fields")
if len(efs) == 0 {
return nil, nil
}
extraFields := make([]logstorage.Field, len(efs))
for i, ef := range efs {
n := strings.Index(ef, "=")
if n <= 0 || n == len(ef)-1 {
return nil, fmt.Errorf(`invalid extra_field format: %q; must be in the form "field=value"`, ef)
}
extraFields[i] = logstorage.Field{
Name: ef[:n],
Value: ef[n+1:],
}
}
return extraFields, nil
}
// GetCommonParamsForSyslog returns common params needed for parsing syslog messages and storing them to the given tenantID.
func GetCommonParamsForSyslog(tenantID logstorage.TenantID, streamFields, ignoreFields []string, extraFields []logstorage.Field) *CommonParams {
// See https://docs.victoriametrics.com/victorialogs/logsql/#unpack_syslog-pipe
if streamFields == nil {
streamFields = []string{
"hostname",
"app_name",
"proc_id",
}
}
cp := &CommonParams{
TenantID: tenantID,
TimeField: "timestamp",
MsgFields: []string{
"message",
},
StreamFields: streamFields,
IgnoreFields: ignoreFields,
ExtraFields: extraFields,
}
return cp
}
// LogMessageProcessor is an interface for log message processors.
type LogMessageProcessor interface {
// AddRow must add row to the LogMessageProcessor with the given timestamp and fields.
//
// If streamFields is non-nil, then the given streamFields must be used as log stream fields instead of pre-configured fields.
//
// The LogMessageProcessor implementation cannot hold references to fields, since the caller can reuse them.
AddRow(timestamp int64, fields, streamFields []logstorage.Field)
// MustClose() must flush all the remaining fields and free up resources occupied by LogMessageProcessor.
MustClose()
}
type logMessageProcessor struct {
mu sync.Mutex
wg sync.WaitGroup
stopCh chan struct{}
lastFlushTime time.Time
cp *CommonParams
lr *logstorage.LogRows
rowsIngestedTotal *metrics.Counter
bytesIngestedTotal *metrics.Counter
}
func (lmp *logMessageProcessor) initPeriodicFlush() {
lmp.lastFlushTime = time.Now()
lmp.wg.Add(1)
go func() {
defer lmp.wg.Done()
d := timeutil.AddJitterToDuration(time.Second)
ticker := time.NewTicker(d)
defer ticker.Stop()
for {
select {
case <-lmp.stopCh:
return
case <-ticker.C:
lmp.mu.Lock()
if time.Since(lmp.lastFlushTime) >= d {
lmp.flushLocked()
}
lmp.mu.Unlock()
}
}
}()
}
// AddRow adds new log message to lmp with the given timestamp and fields.
//
// If streamFields is non-nil, then it is used as log stream fields instead of the pre-configured stream fields.
func (lmp *logMessageProcessor) AddRow(timestamp int64, fields, streamFields []logstorage.Field) {
lmp.rowsIngestedTotal.Inc()
n := logstorage.EstimatedJSONRowLen(fields)
lmp.bytesIngestedTotal.Add(n)
if len(fields) > *MaxFieldsPerLine {
line := logstorage.MarshalFieldsToJSON(nil, fields)
logger.Warnf("dropping log line with %d fields; it exceeds -insert.maxFieldsPerLine=%d; %s", len(fields), *MaxFieldsPerLine, line)
rowsDroppedTotalTooManyFields.Inc()
return
}
lmp.mu.Lock()
defer lmp.mu.Unlock()
lmp.lr.MustAdd(lmp.cp.TenantID, timestamp, fields, streamFields)
if lmp.cp.Debug {
s := lmp.lr.GetRowString(0)
lmp.lr.ResetKeepSettings()
logger.Infof("remoteAddr=%s; requestURI=%s; ignoring log entry because of `debug` arg: %s", lmp.cp.DebugRemoteAddr, lmp.cp.DebugRequestURI, s)
rowsDroppedTotalDebug.Inc()
return
}
if lmp.lr.NeedFlush() {
lmp.flushLocked()
}
}
// flushLocked must be called under locked lmp.mu.
func (lmp *logMessageProcessor) flushLocked() {
lmp.lastFlushTime = time.Now()
vlstorage.MustAddRows(lmp.lr)
lmp.lr.ResetKeepSettings()
}
// MustClose flushes the remaining data to the underlying storage and closes lmp.
func (lmp *logMessageProcessor) MustClose() {
close(lmp.stopCh)
lmp.wg.Wait()
lmp.flushLocked()
logstorage.PutLogRows(lmp.lr)
lmp.lr = nil
}
// NewLogMessageProcessor returns new LogMessageProcessor for the given cp.
//
// MustClose() must be called on the returned LogMessageProcessor when it is no longer needed.
func (cp *CommonParams) NewLogMessageProcessor(protocolName string, isStreamMode bool) LogMessageProcessor {
lr := logstorage.GetLogRows(cp.StreamFields, cp.IgnoreFields, cp.ExtraFields, *defaultMsgValue)
rowsIngestedTotal := metrics.GetOrCreateCounter(fmt.Sprintf("vl_rows_ingested_total{type=%q}", protocolName))
bytesIngestedTotal := metrics.GetOrCreateCounter(fmt.Sprintf("vl_bytes_ingested_total{type=%q}", protocolName))
lmp := &logMessageProcessor{
cp: cp,
lr: lr,
rowsIngestedTotal: rowsIngestedTotal,
bytesIngestedTotal: bytesIngestedTotal,
stopCh: make(chan struct{}),
}
if isStreamMode {
lmp.initPeriodicFlush()
}
return lmp
}
var (
rowsDroppedTotalDebug = metrics.NewCounter(`vl_rows_dropped_total{reason="debug"}`)
rowsDroppedTotalTooManyFields = metrics.NewCounter(`vl_rows_dropped_total{reason="too_many_fields"}`)
)

View File

@@ -1,17 +0,0 @@
package insertutil
import (
"flag"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
)
var (
// MaxLineSizeBytes is the maximum length of a single line for /insert/* handlers
MaxLineSizeBytes = flagutil.NewBytes("insert.maxLineSizeBytes", 256*1024, "The maximum size of a single line, which can be read by /insert/* handlers; "+
"see https://docs.victoriametrics.com/victorialogs/faq/#what-length-a-log-record-is-expected-to-have")
// MaxFieldsPerLine is the maximum number of fields per line for /insert/* handlers
MaxFieldsPerLine = flag.Int("insert.maxFieldsPerLine", 1000, "The maximum number of log fields per line, which can be read by /insert/* handlers; "+
"see https://docs.victoriametrics.com/victorialogs/faq/#how-many-fields-a-single-log-entry-may-contain")
)

View File

@@ -1,146 +0,0 @@
package insertutil
import (
"bytes"
"errors"
"fmt"
"io"
"github.com/VictoriaMetrics/metrics"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/slicesutil"
)
// LineReader reads newline-delimited lines from the underlying reader
type LineReader struct {
// Line contains the next line read after the call to NextLine
//
// The Line contents is valid until the next call to NextLine.
Line []byte
// name is the LineReader name
name string
// r is the underlying reader to read data from
r io.Reader
// buf is a buffer for reading the next line
buf []byte
// bufOffset is the offset at buf to read the next line from
bufOffset int
// err is the last error when reading data from r
err error
// eofReached is set to true when all the data is read from r
eofReached bool
}
// NewLineReader returns LineReader for r.
func NewLineReader(name string, r io.Reader) *LineReader {
return &LineReader{
name: name,
r: r,
}
}
// NextLine reads the next line from the underlying reader.
//
// It returns true if the next line is successfully read into Line.
// If the line length exceeds MaxLineSizeBytes, then this line is skipped
// and an empty line is returned instead.
//
// If false is returned, then no more lines left to read from r.
// Check for Err in this case.
func (lr *LineReader) NextLine() bool {
for {
if lr.bufOffset >= len(lr.buf) {
if lr.err != nil || lr.eofReached {
return false
}
if !lr.readMoreData() {
return false
}
if lr.bufOffset >= len(lr.buf) && lr.eofReached {
return false
}
}
buf := lr.buf[lr.bufOffset:]
if n := bytes.IndexByte(buf, '\n'); n >= 0 {
lr.Line = buf[:n]
lr.bufOffset += n + 1
return true
}
if lr.eofReached {
lr.Line = buf
lr.bufOffset += len(buf)
return true
}
if !lr.readMoreData() {
return false
}
}
}
// Err returns the last error after NextLine call.
func (lr *LineReader) Err() error {
if lr.err == nil {
return nil
}
return fmt.Errorf("%s: %s", lr.name, lr.err)
}
func (lr *LineReader) readMoreData() bool {
if lr.bufOffset > 0 {
lr.buf = append(lr.buf[:0], lr.buf[lr.bufOffset:]...)
lr.bufOffset = 0
}
bufLen := len(lr.buf)
if bufLen >= MaxLineSizeBytes.IntN() {
logger.Warnf("%s: the line length exceeds -insert.maxLineSizeBytes=%d; skipping it; line contents=%q", lr.name, MaxLineSizeBytes.IntN(), lr.buf)
tooLongLinesSkipped.Inc()
return lr.skipUntilNextLine()
}
lr.buf = slicesutil.SetLength(lr.buf, MaxLineSizeBytes.IntN())
n, err := lr.r.Read(lr.buf[bufLen:])
lr.buf = lr.buf[:bufLen+n]
if err != nil {
if errors.Is(err, io.EOF) {
lr.eofReached = true
return true
}
lr.err = fmt.Errorf("cannot read the next line: %s", err)
}
return n > 0
}
var tooLongLinesSkipped = metrics.NewCounter("vl_too_long_lines_skipped_total")
func (lr *LineReader) skipUntilNextLine() bool {
for {
lr.buf = slicesutil.SetLength(lr.buf, MaxLineSizeBytes.IntN())
n, err := lr.r.Read(lr.buf)
lr.buf = lr.buf[:n]
if err != nil {
if errors.Is(err, io.EOF) {
lr.eofReached = true
lr.buf = lr.buf[:0]
return true
}
lr.err = fmt.Errorf("cannot skip the current line: %s", err)
return false
}
if n := bytes.IndexByte(lr.buf, '\n'); n >= 0 {
// Include \n in the buf, so too long line is replaced with an empty line.
// This is needed for maintaining synchorinzation consistency between lines
// in protocols such as Elasticsearch bulk import.
lr.buf = append(lr.buf[:0], lr.buf[n:]...)
return true
}
}
}

View File

@@ -1,161 +0,0 @@
package insertutil
import (
"bytes"
"fmt"
"io"
"reflect"
"testing"
)
func TestLineReader_Success(t *testing.T) {
f := func(data string, linesExpected []string) {
t.Helper()
r := bytes.NewBufferString(data)
lr := NewLineReader("foo", r)
var lines []string
for lr.NextLine() {
lines = append(lines, string(lr.Line))
}
if err := lr.Err(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if lr.NextLine() {
t.Fatalf("expecting error on the second call to NextLine()")
}
if !reflect.DeepEqual(lines, linesExpected) {
t.Fatalf("unexpected lines\ngot\n%q\nwant\n%q", lines, linesExpected)
}
}
f("", nil)
f("\n", []string{""})
f("\n\n", []string{"", ""})
f("foo", []string{"foo"})
f("foo\n", []string{"foo"})
f("\nfoo", []string{"", "foo"})
f("foo\n\n", []string{"foo", ""})
f("foo\nbar", []string{"foo", "bar"})
f("foo\nbar\n", []string{"foo", "bar"})
f("\nfoo\n\nbar\n\n", []string{"", "foo", "", "bar", ""})
}
func TestLineReader_SkipUntilNextLine(t *testing.T) {
f := func(data string, linesExpected []string) {
t.Helper()
r := bytes.NewBufferString(data)
lr := NewLineReader("foo", r)
var lines []string
for lr.NextLine() {
lines = append(lines, string(lr.Line))
}
if err := lr.Err(); err != nil {
t.Fatalf("unexpected error for data=%q: %s", data, err)
}
if lr.NextLine() {
t.Fatalf("expecting error on the second call to NextLine()")
}
if !reflect.DeepEqual(lines, linesExpected) {
t.Fatalf("unexpected lines for data=%q\ngot\n%q\nwant\n%q", data, lines, linesExpected)
}
}
for _, overflow := range []int{0, 100, MaxLineSizeBytes.IntN(), MaxLineSizeBytes.IntN() + 1, 2 * MaxLineSizeBytes.IntN()} {
longLineLen := MaxLineSizeBytes.IntN() + overflow
longLine := string(make([]byte, longLineLen))
// Single long line
data := longLine
f(data, nil)
// Multiple long lines
data = longLine + "\n" + longLine
f(data, []string{""})
data = longLine + "\n" + longLine + "\n"
f(data, []string{"", ""})
// Long line in the middle
data = "foo\n" + longLine + "\nbar"
f(data, []string{"foo", "", "bar"})
// Multiple long lines in the middle
data = "foo\n" + longLine + "\n" + longLine + "\nbar"
f(data, []string{"foo", "", "", "bar"})
// Long line in the end
data = "foo\n" + longLine
f(data, []string{"foo"})
// Long line in the end
data = "foo\n" + longLine + "\n"
f(data, []string{"foo", ""})
}
}
func TestLineReader_Failure(t *testing.T) {
f := func(data string, linesExpected []string) {
t.Helper()
fr := &failureReader{
r: bytes.NewBufferString(data),
}
lr := NewLineReader("foo", fr)
var lines []string
for lr.NextLine() {
lines = append(lines, string(lr.Line))
}
if err := lr.Err(); err == nil {
t.Fatalf("expecting non-nil error")
}
if lr.NextLine() {
t.Fatalf("expecting error on the second call to NextLine()")
}
if err := lr.Err(); err == nil {
t.Fatalf("expecting non-nil error on the second call")
}
if !reflect.DeepEqual(lines, linesExpected) {
t.Fatalf("unexpected lines\ngot\n%q\nwant\n%q", lines, linesExpected)
}
}
f("", nil)
f("foo", nil)
f("foo\n", []string{"foo"})
f("\n", []string{""})
f("foo\nbar", []string{"foo"})
f("foo\nbar\n", []string{"foo", "bar"})
f("\nfoo\nbar\n\n", []string{"", "foo", "bar", ""})
// long line
longLineLen := MaxLineSizeBytes.IntN()
for _, overflow := range []int{0, 100, MaxLineSizeBytes.IntN(), MaxLineSizeBytes.IntN() + 1, 2 * MaxLineSizeBytes.IntN()} {
longLine := string(make([]byte, longLineLen+overflow))
data := longLine
f(data, nil)
data = "foo\n" + longLine
f(data, []string{"foo"})
data = longLine + "\nfoo"
f(data, []string{""})
data = longLine + "\nfoo\n"
f(data, []string{"", "foo"})
}
}
type failureReader struct {
r io.Reader
}
func (r *failureReader) Read(p []byte) (int, error) {
n, _ := r.r.Read(p)
if n > 0 {
return n, nil
}
return 0, fmt.Errorf("some error")
}

View File

@@ -1,56 +0,0 @@
package insertutil
import (
"fmt"
"reflect"
"strings"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
)
// TestLogMessageProcessor implements LogMessageProcessor for testing.
type TestLogMessageProcessor struct {
timestamps []int64
rows []string
}
// AddRow adds row with the given timestamp and fields to tlp
func (tlp *TestLogMessageProcessor) AddRow(timestamp int64, fields, streamFields []logstorage.Field) {
if streamFields != nil {
panic(fmt.Errorf("BUG: streamFields must be nil; got %v", streamFields))
}
tlp.timestamps = append(tlp.timestamps, timestamp)
tlp.rows = append(tlp.rows, string(logstorage.MarshalFieldsToJSON(nil, fields)))
}
// MustClose closes tlp.
func (tlp *TestLogMessageProcessor) MustClose() {
}
// Verify verifies the number of rows, timestamps and results after AddRow calls.
func (tlp *TestLogMessageProcessor) Verify(timestampsExpected []int64, resultExpected string) error {
result := strings.Join(tlp.rows, "\n")
if len(tlp.rows) != len(timestampsExpected) {
return fmt.Errorf("unexpected rows read; got %d; want %d;\nrows read:\n%s\nrows wanted\n%s", len(tlp.rows), len(timestampsExpected), result, resultExpected)
}
if !reflect.DeepEqual(tlp.timestamps, timestampsExpected) {
return fmt.Errorf("unexpected timestamps;\ngot\n%d\nwant\n%d", tlp.timestamps, timestampsExpected)
}
if result != resultExpected {
return fmt.Errorf("unexpected result;\ngot\n%s\nwant\n%s", result, resultExpected)
}
return nil
}
// BenchmarkLogMessageProcessor implements LogMessageProcessor for benchmarks.
type BenchmarkLogMessageProcessor struct{}
// AddRow implements LogMessageProcessor interface.
func (blp *BenchmarkLogMessageProcessor) AddRow(_ int64, _, _ []logstorage.Field) {
}
// MustClose implements LogMessageProcessor interface.
func (blp *BenchmarkLogMessageProcessor) MustClose() {
}

View File

@@ -1,101 +0,0 @@
package insertutil
import (
"fmt"
"math"
"strconv"
"strings"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
)
// ExtractTimestampFromFields extracts timestamp in nanoseconds from the field with the name timeField at fields.
//
// The value for the timeField is set to empty string after returning from the function,
// so it could be ignored during data ingestion.
//
// The current timestamp is returned if fields do not contain a field with timeField name or if the timeField value is empty.
func ExtractTimestampFromFields(timeField string, fields []logstorage.Field) (int64, error) {
for i := range fields {
f := &fields[i]
if f.Name != timeField {
continue
}
nsecs, err := parseTimestamp(f.Value)
if err != nil {
return 0, fmt.Errorf("cannot parse timestamp from field %q: %s", timeField, err)
}
f.Value = ""
if nsecs == 0 {
nsecs = time.Now().UnixNano()
}
return nsecs, nil
}
return time.Now().UnixNano(), nil
}
func parseTimestamp(s string) (int64, error) {
if s == "" || s == "0" {
return time.Now().UnixNano(), nil
}
if len(s) <= len("YYYY") || s[len("YYYY")] != '-' {
return ParseUnixTimestamp(s)
}
nsecs, ok := logstorage.TryParseTimestampRFC3339Nano(s)
if !ok {
return 0, fmt.Errorf("cannot unmarshal rfc3339 timestamp %q", s)
}
return nsecs, nil
}
// ParseUnixTimestamp parses s as unix timestamp in seconds, milliseconds, microseconds or nanoseconds and returns the parsed timestamp in nanoseconds.
func ParseUnixTimestamp(s string) (int64, error) {
if strings.IndexByte(s, '.') >= 0 {
// Parse timestamp as floating-point value
f, err := strconv.ParseFloat(s, 64)
if err != nil {
return 0, fmt.Errorf("cannot parse unix timestamp from %q: %w", s, err)
}
if f < (1<<31) && f >= (-1<<31) {
// The timestamp is in seconds.
return int64(f * 1e9), nil
}
if f < 1e3*(1<<31) && f >= 1e3*(-1<<31) {
// The timestamp is in milliseconds.
return int64(f * 1e6), nil
}
if f < 1e6*(1<<31) && f >= 1e6*(-1<<31) {
// The timestamp is in microseconds.
return int64(f * 1e3), nil
}
// The timestamp is in nanoseconds
if f > math.MaxInt64 {
return 0, fmt.Errorf("too big timestamp in nanoseconds: %v; mustn't exceed %v", f, int64(math.MaxInt64))
}
if f < math.MinInt64 {
return 0, fmt.Errorf("too small timestamp in nanoseconds: %v; must be bigger or equal to %v", f, int64(math.MinInt64))
}
return int64(f), nil
}
// Parse timestamp as integer
n, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return 0, fmt.Errorf("cannot parse unix timestamp from %q: %w", s, err)
}
if n < (1<<31) && n >= (-1<<31) {
// The timestamp is in seconds.
return n * 1e9, nil
}
if n < 1e3*(1<<31) && n >= 1e3*(-1<<31) {
// The timestamp is in milliseconds.
return n * 1e6, nil
}
if n < 1e6*(1<<31) && n >= 1e6*(-1<<31) {
// The timestamp is in microseconds.
return n * 1e3, nil
}
// The timestamp is in nanoseconds
return n, nil
}

View File

@@ -1,158 +0,0 @@
package insertutil
import (
"testing"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
)
func TestParseUnixTimestamp_Success(t *testing.T) {
f := func(s string, timestampExpected int64) {
t.Helper()
timestamp, err := ParseUnixTimestamp(s)
if err != nil {
t.Fatalf("unexpected error in ParseUnixTimestamp(%q): %s", s, err)
}
if timestamp != timestampExpected {
t.Fatalf("unexpected timestamp returned from ParseUnixTimestamp(%q); got %d; want %d", s, timestamp, timestampExpected)
}
}
f("0", 0)
// nanoseconds
f("-1234567890123456789", -1234567890123456789)
f("1234567890123456789", 1234567890123456789)
// microseconds
f("-1234567890123456", -1234567890123456000)
f("1234567890123456", 1234567890123456000)
f("1234567890123456.789", 1234567890123456768)
// milliseconds
f("-1234567890123", -1234567890123000000)
f("1234567890123", 1234567890123000000)
f("1234567890123.456", 1234567890123456000)
// seconds
f("-1234567890", -1234567890000000000)
f("1234567890", 1234567890000000000)
f("-1234567890.123456", -1234567890123456000)
}
func TestParseUnixTimestamp_Failure(t *testing.T) {
f := func(s string) {
t.Helper()
_, err := ParseUnixTimestamp(s)
if err == nil {
t.Fatalf("expecting non-nil error in ParseUnixTimestamp(%q)", s)
}
}
// non-numeric timestamp
f("")
f("foobar")
f("foo.bar")
// too big timestamp
f("12345678901234567890")
f("-12345678901234567890")
f("12345678901234567890.235424")
f("-12345678901234567890.235424")
}
func TestExtractTimestampFromFields_Success(t *testing.T) {
f := func(timeField string, fields []logstorage.Field, nsecsExpected int64) {
t.Helper()
nsecs, err := ExtractTimestampFromFields(timeField, fields)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if nsecs != nsecsExpected {
t.Fatalf("unexpected nsecs; got %d; want %d", nsecs, nsecsExpected)
}
for _, f := range fields {
if f.Name == timeField {
if f.Value != "" {
t.Fatalf("unexpected value for field %s; got %q; want %q", timeField, f.Value, "")
}
}
}
}
// UTC time
f("time", []logstorage.Field{
{Name: "foo", Value: "bar"},
{Name: "time", Value: "2024-06-18T23:37:20Z"},
}, 1718753840000000000)
// Time with timezone
f("time", []logstorage.Field{
{Name: "foo", Value: "bar"},
{Name: "time", Value: "2024-06-18T23:37:20+08:00"},
}, 1718725040000000000)
// SQL datetime format
f("time", []logstorage.Field{
{Name: "foo", Value: "bar"},
{Name: "time", Value: "2024-06-18 23:37:20.123-05:30"},
}, 1718773640123000000)
// Time with nanosecond precision
f("time", []logstorage.Field{
{Name: "time", Value: "2024-06-18T23:37:20.123456789-05:30"},
{Name: "foo", Value: "bar"},
}, 1718773640123456789)
// Unix timestamp in nanoseconds
f("time", []logstorage.Field{
{Name: "foo", Value: "bar"},
{Name: "time", Value: "1718773640123456789"},
}, 1718773640123456789)
// Unix timestamp in microseconds
f("time", []logstorage.Field{
{Name: "foo", Value: "bar"},
{Name: "time", Value: "1718773640123456"},
}, 1718773640123456000)
// Unix timestamp in milliseconds
f("time", []logstorage.Field{
{Name: "foo", Value: "bar"},
{Name: "time", Value: "1718773640123"},
}, 1718773640123000000)
// Unix timestamp in seconds
f("time", []logstorage.Field{
{Name: "foo", Value: "bar"},
{Name: "time", Value: "1718773640"},
}, 1718773640000000000)
}
func TestExtractTimestampFromFields_Error(t *testing.T) {
f := func(s string) {
t.Helper()
fields := []logstorage.Field{
{Name: "time", Value: s},
}
nsecs, err := ExtractTimestampFromFields("time", fields)
if err == nil {
t.Fatalf("expecting non-nil error")
}
if nsecs != 0 {
t.Fatalf("unexpected nsecs; got %d; want %d", nsecs, 0)
}
}
// invalid time
f("foobar")
// incomplete time
f("2024-06-18")
f("2024-06-18T23:37")
}

View File

@@ -1,237 +0,0 @@
package journald
import (
"bytes"
"encoding/binary"
"flag"
"fmt"
"net/http"
"regexp"
"slices"
"strconv"
"strings"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/protoparserutil"
"github.com/VictoriaMetrics/metrics"
)
// See https://github.com/systemd/systemd/blob/main/src/libsystemd/sd-journal/journal-file.c#L1703
const journaldEntryMaxNameLen = 64
var allowedJournaldEntryNameChars = regexp.MustCompile(`^[A-Z_][A-Z0-9_]*`)
var (
journaldStreamFields = flagutil.NewArrayString("journald.streamFields", "Comma-separated list of fields to use as log stream fields for logs ingested over journald protocol. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/journald/#stream-fields")
journaldIgnoreFields = flagutil.NewArrayString("journald.ignoreFields", "Comma-separated list of fields to ignore for logs ingested over journald protocol. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/journald/#dropping-fields")
journaldTimeField = flag.String("journald.timeField", "__REALTIME_TIMESTAMP", "Field to use as a log timestamp for logs ingested via journald protocol. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/journald/#time-field")
journaldTenantID = flag.String("journald.tenantID", "0:0", "TenantID for logs ingested via the Journald endpoint. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/journald/#multitenancy")
journaldIncludeEntryMetadata = flag.Bool("journald.includeEntryMetadata", false, "Include journal entry fields, which with double underscores.")
maxRequestSize = flagutil.NewBytes("journald.maxRequestSize", 64*1024*1024, "The maximum size in bytes of a single journald request")
)
func getCommonParams(r *http.Request) (*insertutil.CommonParams, error) {
cp, err := insertutil.GetCommonParams(r)
if err != nil {
return nil, err
}
if cp.TenantID.AccountID == 0 && cp.TenantID.ProjectID == 0 {
tenantID, err := logstorage.ParseTenantID(*journaldTenantID)
if err != nil {
return nil, fmt.Errorf("cannot parse -journald.tenantID=%q for journald: %w", *journaldTenantID, err)
}
cp.TenantID = tenantID
}
if cp.TimeField != "" {
cp.TimeField = *journaldTimeField
}
if len(cp.StreamFields) == 0 {
cp.StreamFields = *journaldStreamFields
}
if len(cp.IgnoreFields) == 0 {
cp.IgnoreFields = *journaldIgnoreFields
}
cp.MsgFields = []string{"MESSAGE"}
return cp, nil
}
// RequestHandler processes Journald Export insert requests
func RequestHandler(path string, w http.ResponseWriter, r *http.Request) bool {
switch path {
case "/upload":
if r.Header.Get("Content-Type") != "application/vnd.fdo.journal" {
httpserver.Errorf(w, r, "only application/vnd.fdo.journal encoding is supported for Journald")
return true
}
handleJournald(r, w)
return true
default:
return false
}
}
// handleJournald parses Journal binary entries
func handleJournald(r *http.Request, w http.ResponseWriter) {
startTime := time.Now()
requestsJournaldTotal.Inc()
cp, err := getCommonParams(r)
if err != nil {
errorsTotal.Inc()
httpserver.Errorf(w, r, "cannot parse common params from request: %s", err)
return
}
if err := vlstorage.CanWriteData(); err != nil {
errorsTotal.Inc()
httpserver.Errorf(w, r, "%s", err)
return
}
encoding := r.Header.Get("Content-Encoding")
err = protoparserutil.ReadUncompressedData(r.Body, encoding, maxRequestSize, func(data []byte) error {
lmp := cp.NewLogMessageProcessor("journald", false)
err := parseJournaldRequest(data, lmp, cp)
lmp.MustClose()
return err
})
if err != nil {
errorsTotal.Inc()
httpserver.Errorf(w, r, "cannot read journald protocol data: %s", err)
return
}
// systemd starting release v258 will support compression, which starts working after negotiation: it expects supported compression
// algorithms list in Accept-Encoding response header in a format "<algorithm_1>[:<priority_1>][;<algorithm_2>:<priority_2>]"
// See https://github.com/systemd/systemd/pull/34822
w.Header().Set("Accept-Encoding", "zstd")
// update requestJournaldDuration only for successfully parsed requests
// There is no need in updating requestJournaldDuration for request errors,
// since their timings are usually much smaller than the timing for successful request parsing.
requestJournaldDuration.UpdateDuration(startTime)
}
var (
requestsJournaldTotal = metrics.NewCounter(`vl_http_requests_total{path="/insert/journald/upload"}`)
errorsTotal = metrics.NewCounter(`vl_http_errors_total{path="/insert/journald/upload"}`)
requestJournaldDuration = metrics.NewHistogram(`vl_http_request_duration_seconds{path="/insert/journald/upload"}`)
)
// See https://systemd.io/JOURNAL_EXPORT_FORMATS/#journal-export-format
func parseJournaldRequest(data []byte, lmp insertutil.LogMessageProcessor, cp *insertutil.CommonParams) error {
var fields []logstorage.Field
var ts int64
var size uint64
var name, value string
var line []byte
currentTimestamp := time.Now().UnixNano()
for len(data) > 0 {
idx := bytes.IndexByte(data, '\n')
switch {
case idx > 0:
// process fields
line = data[:idx]
data = data[idx+1:]
case idx == 0:
// next message or end of file
// double new line is a separator for the next message
if len(fields) > 0 {
if ts == 0 {
ts = currentTimestamp
}
lmp.AddRow(ts, fields, nil)
fields = fields[:0]
}
// skip newline separator
data = data[1:]
continue
case idx < 0:
return fmt.Errorf("missing new line separator, unread data left=%d", len(data))
}
idx = bytes.IndexByte(line, '=')
// could b either e key=value\n pair
// or just key\n
// with binary data at the buffer
if idx > 0 {
name = bytesutil.ToUnsafeString(line[:idx])
value = bytesutil.ToUnsafeString(line[idx+1:])
} else {
name = bytesutil.ToUnsafeString(line)
if len(data) == 0 {
return fmt.Errorf("unexpected zero data for binary field value of key=%s", name)
}
// size of binary data encoded as le i64 at the begging
idx, err := binary.Decode(data, binary.LittleEndian, &size)
if err != nil {
return fmt.Errorf("failed to extract binary field %q value size: %w", name, err)
}
// skip binary data size
data = data[idx:]
if size == 0 {
return fmt.Errorf("unexpected zero binary data size decoded %d", size)
}
if int(size) > len(data) {
return fmt.Errorf("binary data size=%d cannot exceed size of the data at buffer=%d", size, len(data))
}
value = bytesutil.ToUnsafeString(data[:size])
data = data[int(size):]
// binary data must has new line separator for the new line or next field
if len(data) == 0 {
return fmt.Errorf("unexpected empty buffer after binary field=%s read", name)
}
lastB := data[0]
if lastB != '\n' {
return fmt.Errorf("expected new line separator after binary field=%s, got=%s", name, string(lastB))
}
data = data[1:]
}
if len(name) > journaldEntryMaxNameLen {
return fmt.Errorf("journald entry name should not exceed %d symbols, got: %q", journaldEntryMaxNameLen, name)
}
if !allowedJournaldEntryNameChars.MatchString(name) {
return fmt.Errorf("journald entry name should consist of `A-Z0-9_` characters and must start from non-digit symbol")
}
if name == cp.TimeField {
n, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return fmt.Errorf("failed to parse Journald timestamp, %w", err)
}
ts = n * 1e3
continue
}
if slices.Contains(cp.MsgFields, name) {
name = "_msg"
}
if *journaldIncludeEntryMetadata || !strings.HasPrefix(name, "__") {
fields = append(fields, logstorage.Field{
Name: name,
Value: value,
})
}
}
if len(fields) > 0 {
if ts == 0 {
ts = currentTimestamp
}
lmp.AddRow(ts, fields, nil)
}
return nil
}

View File

@@ -1,68 +0,0 @@
package journald
import (
"testing"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
)
func TestPushJournaldOk(t *testing.T) {
f := func(src string, timestampsExpected []int64, resultExpected string) {
t.Helper()
tlp := &insertutil.TestLogMessageProcessor{}
cp := &insertutil.CommonParams{
TimeField: "__REALTIME_TIMESTAMP",
MsgFields: []string{"MESSAGE"},
}
if err := parseJournaldRequest([]byte(src), tlp, cp); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if err := tlp.Verify(timestampsExpected, resultExpected); err != nil {
t.Fatal(err)
}
}
// Single event
f("__REALTIME_TIMESTAMP=91723819283\nMESSAGE=Test message\n",
[]int64{91723819283000},
"{\"_msg\":\"Test message\"}",
)
// Multiple events
f("__REALTIME_TIMESTAMP=91723819283\nMESSAGE=Test message\n\n__REALTIME_TIMESTAMP=91723819284\nMESSAGE=Test message2\n",
[]int64{91723819283000, 91723819284000},
"{\"_msg\":\"Test message\"}\n{\"_msg\":\"Test message2\"}",
)
// Parse binary data
f("__CURSOR=s=e0afe8412a6a49d2bfcf66aa7927b588;i=1f06;b=f778b6e2f7584a77b991a2366612a7b5;m=300bdfd420;t=62526e1182354;x=930dc44b370963b7\nE=JobStateChanged\n__REALTIME_TIMESTAMP=1729698775704404\n__MONOTONIC_TIMESTAMP=206357648416\n__SEQNUM=7942\n__SEQNUM_ID=e0afe8412a6a49d2bfcf66aa7927b588\n_BOOT_ID=f778b6e2f7584a77b991a2366612a7b5\n_UID=0\n_GID=0\n_MACHINE_ID=a4a970370c30a925df02a13c67167847\n_HOSTNAME=ecd5e4555787\n_RUNTIME_SCOPE=system\n_TRANSPORT=journal\n_CAP_EFFECTIVE=1ffffffffff\n_SYSTEMD_CGROUP=/init.scope\n_SYSTEMD_UNIT=init.scope\n_SYSTEMD_SLICE=-.slice\nCODE_FILE=<stdin>\nCODE_LINE=1\nCODE_FUNC=<module>\nSYSLOG_IDENTIFIER=python3\n_COMM=python3\n_EXE=/usr/bin/python3.12\n_CMDLINE=python3\nMESSAGE\n\x13\x00\x00\x00\x00\x00\x00\x00foo\nbar\n\n\nasda\nasda\n_PID=2763\n_SOURCE_REALTIME_TIMESTAMP=1729698775704375\n\n",
[]int64{1729698775704404000},
"{\"E\":\"JobStateChanged\",\"_BOOT_ID\":\"f778b6e2f7584a77b991a2366612a7b5\",\"_UID\":\"0\",\"_GID\":\"0\",\"_MACHINE_ID\":\"a4a970370c30a925df02a13c67167847\",\"_HOSTNAME\":\"ecd5e4555787\",\"_RUNTIME_SCOPE\":\"system\",\"_TRANSPORT\":\"journal\",\"_CAP_EFFECTIVE\":\"1ffffffffff\",\"_SYSTEMD_CGROUP\":\"/init.scope\",\"_SYSTEMD_UNIT\":\"init.scope\",\"_SYSTEMD_SLICE\":\"-.slice\",\"CODE_FILE\":\"\\u003cstdin>\",\"CODE_LINE\":\"1\",\"CODE_FUNC\":\"\\u003cmodule>\",\"SYSLOG_IDENTIFIER\":\"python3\",\"_COMM\":\"python3\",\"_EXE\":\"/usr/bin/python3.12\",\"_CMDLINE\":\"python3\",\"_msg\":\"foo\\nbar\\n\\n\\nasda\\nasda\",\"_PID\":\"2763\",\"_SOURCE_REALTIME_TIMESTAMP\":\"1729698775704375\"}",
)
}
func TestPushJournald_Failure(t *testing.T) {
f := func(data string) {
t.Helper()
tlp := &insertutil.TestLogMessageProcessor{}
cp := &insertutil.CommonParams{
TimeField: "__REALTIME_TIMESTAMP",
MsgFields: []string{"MESSAGE"},
}
if err := parseJournaldRequest([]byte(data), tlp, cp); err == nil {
t.Fatalf("expected non nil error")
}
}
// missing new line terminator for binary encoded message
f("__CURSOR=s=e0afe8412a6a49d2bfcf66aa7927b588;i=1f06;b=f778b6e2f7584a77b991a2366612a7b5;m=300bdfd420;t=62526e1182354;x=930dc44b370963b7\n__REALTIME_TIMESTAMP=1729698775704404\nMESSAGE\n\x13\x00\x00\x00\x00\x00\x00\x00foo\nbar\n\n\nasdaasda2")
// missing new line terminator
f("__REALTIME_TIMESTAMP=91723819283\n=Test message")
// empty field name
f("__REALTIME_TIMESTAMP=91723819283\n=Test message\n")
// field name starting with number
f("__REALTIME_TIMESTAMP=91723819283\n1incorrect=Test message\n")
// field name exceeds 64 limit
f("__REALTIME_TIMESTAMP=91723819283\ntoolooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongcorrecooooooooooooong=Test message\n")
// Only allow A-Z0-9 and '_'
f("__REALTIME_TIMESTAMP=91723819283\nbadC!@$!@$as=Test message\n")
}

View File

@@ -1,109 +0,0 @@
package jsonline
import (
"fmt"
"io"
"net/http"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/protoparserutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/writeconcurrencylimiter"
"github.com/VictoriaMetrics/metrics"
)
// RequestHandler processes jsonline insert requests
func RequestHandler(w http.ResponseWriter, r *http.Request) {
startTime := time.Now()
w.Header().Add("Content-Type", "application/json")
if r.Method != "POST" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
requestsTotal.Inc()
cp, err := insertutil.GetCommonParams(r)
if err != nil {
httpserver.Errorf(w, r, "%s", err)
return
}
if err := vlstorage.CanWriteData(); err != nil {
httpserver.Errorf(w, r, "%s", err)
return
}
encoding := r.Header.Get("Content-Encoding")
reader, err := protoparserutil.GetUncompressedReader(r.Body, encoding)
if err != nil {
logger.Errorf("cannot decode jsonline request: %s", err)
return
}
defer protoparserutil.PutUncompressedReader(reader)
lmp := cp.NewLogMessageProcessor("jsonline", true)
streamName := fmt.Sprintf("remoteAddr=%s, requestURI=%q", httpserver.GetQuotedRemoteAddr(r), r.RequestURI)
processStreamInternal(streamName, reader, cp.TimeField, cp.MsgFields, lmp)
lmp.MustClose()
requestDuration.UpdateDuration(startTime)
}
func processStreamInternal(streamName string, r io.Reader, timeField string, msgFields []string, lmp insertutil.LogMessageProcessor) {
wcr := writeconcurrencylimiter.GetReader(r)
defer writeconcurrencylimiter.PutReader(wcr)
lr := insertutil.NewLineReader(streamName, wcr)
n := 0
for {
ok, err := readLine(lr, timeField, msgFields, lmp)
wcr.DecConcurrency()
if err != nil {
errorsTotal.Inc()
logger.Warnf("jsonline: cannot read line #%d in /jsonline request: %s", n, err)
}
if !ok {
return
}
n++
}
}
func readLine(lr *insertutil.LineReader, timeField string, msgFields []string, lmp insertutil.LogMessageProcessor) (bool, error) {
var line []byte
for len(line) == 0 {
if !lr.NextLine() {
err := lr.Err()
return false, err
}
line = lr.Line
}
p := logstorage.GetJSONParser()
defer logstorage.PutJSONParser(p)
if err := p.ParseLogMessage(line); err != nil {
return true, fmt.Errorf("cannot parse json-encoded line: %w; line contents: %q", err, line)
}
ts, err := insertutil.ExtractTimestampFromFields(timeField, p.Fields)
if err != nil {
return true, fmt.Errorf("cannot get timestamp from json-encoded line: %w; line contents: %q", err, line)
}
logstorage.RenameField(p.Fields, msgFields, "_msg")
lmp.AddRow(ts, p.Fields, nil)
return true, nil
}
var (
requestsTotal = metrics.NewCounter(`vl_http_requests_total{path="/insert/jsonline"}`)
errorsTotal = metrics.NewCounter(`vl_http_errors_total{path="/insert/jsonline"}`)
requestDuration = metrics.NewHistogram(`vl_http_request_duration_seconds{path="/insert/jsonline"}`)
)

View File

@@ -1,79 +0,0 @@
package jsonline
import (
"bytes"
"testing"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
)
func TestProcessStreamInternal(t *testing.T) {
f := func(data, timeField, msgField string, timestampsExpected []int64, resultExpected string) {
t.Helper()
msgFields := []string{msgField}
tlp := &insertutil.TestLogMessageProcessor{}
r := bytes.NewBufferString(data)
processStreamInternal("test", r, timeField, msgFields, tlp)
if err := tlp.Verify(timestampsExpected, resultExpected); err != nil {
t.Fatal(err)
}
}
data := `{"@timestamp":"2023-06-06T04:48:11.735Z","log":{"offset":71770,"file":{"path":"/var/log/auth.log"}},"message":"foobar"}
{"@timestamp":"2023-06-06T04:48:12.735+01:00","message":"baz"}
{"message":"xyz","@timestamp":"2023-06-06 04:48:13.735Z","x":"y"}
`
timeField := "@timestamp"
msgField := "message"
timestampsExpected := []int64{1686026891735000000, 1686023292735000000, 1686026893735000000}
resultExpected := `{"log.offset":"71770","log.file.path":"/var/log/auth.log","_msg":"foobar"}
{"_msg":"baz"}
{"_msg":"xyz","x":"y"}`
f(data, timeField, msgField, timestampsExpected, resultExpected)
// Non-existing msgField
data = `{"@timestamp":"2023-06-06T04:48:11.735Z","log":{"offset":71770,"file":{"path":"/var/log/auth.log"}},"message":"foobar"}
{"@timestamp":"2023-06-06T04:48:12.735+01:00","message":"baz"}
`
timeField = "@timestamp"
msgField = "foobar"
timestampsExpected = []int64{1686026891735000000, 1686023292735000000}
resultExpected = `{"log.offset":"71770","log.file.path":"/var/log/auth.log","message":"foobar"}
{"message":"baz"}`
f(data, timeField, msgField, timestampsExpected, resultExpected)
// invalid json
data = "foobar"
timeField = "@timestamp"
msgField = "aaa"
timestampsExpected = nil
resultExpected = ``
f(data, timeField, msgField, timestampsExpected, resultExpected)
// invalid timestamp field
data = `{"time":"foobar"}`
timeField = "time"
msgField = "abc"
timestampsExpected = nil
resultExpected = ``
f(data, timeField, msgField, timestampsExpected, resultExpected)
// invalid lines among valid lines
data = `
dsfodmasd
{"time":"2023-06-06T04:48:11.735Z","log":{"offset":71770,"file":{"path":"/var/log/auth.log"}},"message":"foobar"}
invalid line
{"time":"2023-06-06T04:48:12.735+01:00","message":"baz"}
asbsdf
`
timeField = "time"
msgField = "message"
timestampsExpected = []int64{1686026891735000000, 1686023292735000000}
resultExpected = `{"log.offset":"71770","log.file.path":"/var/log/auth.log","_msg":"foobar"}
{"_msg":"baz"}`
f(data, timeField, msgField, timestampsExpected, resultExpected)
}

View File

@@ -1,86 +0,0 @@
package loki
import (
"flag"
"fmt"
"net/http"
"strconv"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httputil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
)
var disableMessageParsing = flag.Bool("loki.disableMessageParsing", false, "Whether to disable automatic parsing of JSON-encoded log fields inside Loki log message into distinct log fields")
// RequestHandler processes Loki insert requests
func RequestHandler(path string, w http.ResponseWriter, r *http.Request) bool {
switch path {
case "/api/v1/push":
handleInsert(r, w)
return true
case "/ready":
// See https://grafana.com/docs/loki/latest/api/#identify-ready-loki-instance
w.WriteHeader(http.StatusOK)
w.Write([]byte("ready"))
return true
default:
return false
}
}
// See https://grafana.com/docs/loki/latest/api/#push-log-entries-to-loki
func handleInsert(r *http.Request, w http.ResponseWriter) {
contentType := r.Header.Get("Content-Type")
switch contentType {
case "application/json":
handleJSON(r, w)
default:
// Protobuf request body should be handled by default according to https://grafana.com/docs/loki/latest/api/#push-log-entries-to-loki
handleProtobuf(r, w)
}
}
type commonParams struct {
cp *insertutil.CommonParams
// Whether to parse JSON inside plaintext log message.
//
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8486
parseMessage bool
}
func getCommonParams(r *http.Request) (*commonParams, error) {
cp, err := insertutil.GetCommonParams(r)
if err != nil {
return nil, err
}
// If parsed tenant is (0,0) it is likely to be default tenant
// Try parsing tenant from Loki headers
if cp.TenantID.AccountID == 0 && cp.TenantID.ProjectID == 0 {
org := r.Header.Get("X-Scope-OrgID")
if org != "" {
tenantID, err := logstorage.ParseTenantID(org)
if err != nil {
return nil, err
}
cp.TenantID = tenantID
}
}
parseMessage := !*disableMessageParsing
if rv := httputil.GetRequestValue(r, "disable_message_parsing", "VL-Loki-Disable-Message-Parsing"); rv != "" {
bv, err := strconv.ParseBool(rv)
if err != nil {
return nil, fmt.Errorf("cannot parse dusable_message_parsing=%q: %s", rv, err)
}
parseMessage = !bv
}
return &commonParams{
cp: cp,
parseMessage: parseMessage,
}, nil
}

View File

@@ -1,226 +0,0 @@
package loki
import (
"fmt"
"net/http"
"time"
"github.com/VictoriaMetrics/metrics"
"github.com/valyala/fastjson"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/protoparserutil"
)
var maxRequestSize = flagutil.NewBytes("loki.maxRequestSize", 64*1024*1024, "The maximum size in bytes of a single Loki request")
var parserPool fastjson.ParserPool
func handleJSON(r *http.Request, w http.ResponseWriter) {
startTime := time.Now()
requestsJSONTotal.Inc()
cp, err := getCommonParams(r)
if err != nil {
httpserver.Errorf(w, r, "cannot parse common params from request: %s", err)
return
}
if err := vlstorage.CanWriteData(); err != nil {
httpserver.Errorf(w, r, "%s", err)
return
}
encoding := r.Header.Get("Content-Encoding")
err = protoparserutil.ReadUncompressedData(r.Body, encoding, maxRequestSize, func(data []byte) error {
lmp := cp.cp.NewLogMessageProcessor("loki_json", false)
useDefaultStreamFields := len(cp.cp.StreamFields) == 0
err := parseJSONRequest(data, lmp, cp.cp.MsgFields, useDefaultStreamFields, cp.parseMessage)
lmp.MustClose()
return err
})
if err != nil {
httpserver.Errorf(w, r, "cannot read Loki json data: %s", err)
return
}
// update requestJSONDuration only for successfully parsed requests
// There is no need in updating requestJSONDuration for request errors,
// since their timings are usually much smaller than the timing for successful request parsing.
requestJSONDuration.UpdateDuration(startTime)
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8505
w.WriteHeader(http.StatusNoContent)
}
var (
requestsJSONTotal = metrics.NewCounter(`vl_http_requests_total{path="/insert/loki/api/v1/push",format="json"}`)
requestJSONDuration = metrics.NewHistogram(`vl_http_request_duration_seconds{path="/insert/loki/api/v1/push",format="json"}`)
)
func parseJSONRequest(data []byte, lmp insertutil.LogMessageProcessor, msgFields []string, useDefaultStreamFields, parseMessage bool) error {
p := parserPool.Get()
defer parserPool.Put(p)
v, err := p.ParseBytes(data)
if err != nil {
return fmt.Errorf("cannot parse JSON request body: %w", err)
}
streamsV := v.Get("streams")
if streamsV == nil {
return fmt.Errorf("missing `streams` item in the parsed JSON")
}
streams, err := streamsV.Array()
if err != nil {
return fmt.Errorf("`streams` item in the parsed JSON must contain an array; got %q", streamsV)
}
fields := getFields()
defer putFields(fields)
var msgParser *logstorage.JSONParser
if parseMessage {
msgParser = logstorage.GetJSONParser()
defer logstorage.PutJSONParser(msgParser)
}
currentTimestamp := time.Now().UnixNano()
for _, stream := range streams {
// populate common labels from `stream` dict
fields.fields = fields.fields[:0]
labelsV := stream.Get("stream")
var labels *fastjson.Object
if labelsV != nil {
o, err := labelsV.Object()
if err != nil {
return fmt.Errorf("`stream` item in the parsed JSON must contain an object; got %q", labelsV)
}
labels = o
}
labels.Visit(func(k []byte, v *fastjson.Value) {
vStr, errLocal := v.StringBytes()
if errLocal != nil {
err = fmt.Errorf("unexpected label value type for %q:%q; want string", k, v)
return
}
fields.fields = append(fields.fields, logstorage.Field{
Name: bytesutil.ToUnsafeString(k),
Value: bytesutil.ToUnsafeString(vStr),
})
})
if err != nil {
return fmt.Errorf("error when parsing `stream` object: %w", err)
}
// populate messages from `values` array
linesV := stream.Get("values")
if linesV == nil {
return fmt.Errorf("missing `values` item in the parsed `stream` object %q", stream)
}
lines, err := linesV.Array()
if err != nil {
return fmt.Errorf("`values` item in the parsed JSON must contain an array; got %q", linesV)
}
commonFieldsLen := len(fields.fields)
for _, line := range lines {
fields.fields = fields.fields[:commonFieldsLen]
lineA, err := line.Array()
if err != nil {
return fmt.Errorf("unexpected contents of `values` item; want array; got %q", line)
}
if len(lineA) < 2 || len(lineA) > 3 {
return fmt.Errorf("unexpected number of values in `values` item array %q; got %d want 2 or 3", line, len(lineA))
}
// parse timestamp
timestamp, err := lineA[0].StringBytes()
if err != nil {
return fmt.Errorf("unexpected log timestamp type for %q; want string", lineA[0])
}
ts, err := parseLokiTimestamp(bytesutil.ToUnsafeString(timestamp))
if err != nil {
return fmt.Errorf("cannot parse log timestamp %q: %w", timestamp, err)
}
if ts == 0 {
ts = currentTimestamp
}
// parse structured metadata - see https://grafana.com/docs/loki/latest/reference/loki-http-api/#ingest-logs
if len(lineA) > 2 {
structuredMetadata, err := lineA[2].Object()
if err != nil {
return fmt.Errorf("unexpected structured metadata type for %q; want JSON object", lineA[2])
}
structuredMetadata.Visit(func(k []byte, v *fastjson.Value) {
vStr, errLocal := v.StringBytes()
if errLocal != nil {
err = fmt.Errorf("unexpected label value type for %q:%q; want string", k, v)
return
}
fields.fields = append(fields.fields, logstorage.Field{
Name: bytesutil.ToUnsafeString(k),
Value: bytesutil.ToUnsafeString(vStr),
})
})
if err != nil {
return fmt.Errorf("error when parsing `structuredMetadata` object: %w", err)
}
}
// parse log message
msg, err := lineA[1].StringBytes()
if err != nil {
return fmt.Errorf("unexpected log message type for %q; want string", lineA[1])
}
allowMsgRenaming := false
fields.fields, allowMsgRenaming = addMsgField(fields.fields, msgParser, bytesutil.ToUnsafeString(msg))
var streamFields []logstorage.Field
if useDefaultStreamFields {
streamFields = fields.fields[:commonFieldsLen]
}
if allowMsgRenaming {
logstorage.RenameField(fields.fields[commonFieldsLen:], msgFields, "_msg")
}
lmp.AddRow(ts, fields.fields, streamFields)
}
}
return nil
}
func addMsgField(dst []logstorage.Field, msgParser *logstorage.JSONParser, msg string) ([]logstorage.Field, bool) {
if msgParser == nil || len(msg) < 2 || msg[0] != '{' || msg[len(msg)-1] != '}' {
return append(dst, logstorage.Field{
Name: "_msg",
Value: msg,
}), false
}
if msgParser != nil && len(msg) >= 2 && msg[0] == '{' && msg[len(msg)-1] == '}' {
if err := msgParser.ParseLogMessage(bytesutil.ToUnsafeBytes(msg)); err == nil {
return append(dst, msgParser.Fields...), true
}
}
return append(dst, logstorage.Field{
Name: "_msg",
Value: msg,
}), false
}
func parseLokiTimestamp(s string) (int64, error) {
if s == "" {
// Special case - an empty timestamp must be substituted with the current time by the caller.
return 0, nil
}
return insertutil.ParseUnixTimestamp(s)
}

View File

@@ -1,169 +0,0 @@
package loki
import (
"testing"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
)
func TestParseJSONRequest_Failure(t *testing.T) {
f := func(s string) {
t.Helper()
tlp := &insertutil.TestLogMessageProcessor{}
if err := parseJSONRequest([]byte(s), tlp, nil, false, false); err == nil {
t.Fatalf("expecting non-nil error")
}
if err := tlp.Verify(nil, ""); err != nil {
t.Fatalf("unexpected error: %s", err)
}
}
f(``)
// Invalid json
f(`{}`)
f(`[]`)
f(`"foo"`)
f(`123`)
// invalid type for `streams` item
f(`{"streams":123}`)
// Missing `values` item
f(`{"streams":[{}]}`)
// Invalid type for `values` item
f(`{"streams":[{"values":"foobar"}]}`)
// Invalid type for `stream` item
f(`{"streams":[{"stream":[],"values":[]}]}`)
// Invalid type for `values` individual item
f(`{"streams":[{"values":[123]}]}`)
// Invalid length of `values` individual item
f(`{"streams":[{"values":[[]]}]}`)
f(`{"streams":[{"values":[["123"]]}]}`)
f(`{"streams":[{"values":[["123","456","789","8123"]]}]}`)
// Invalid type for timestamp inside `values` individual item
f(`{"streams":[{"values":[[123,"456"]}]}`)
// Invalid type for log message
f(`{"streams":[{"values":[["123",1234]]}]}`)
// invalid structured metadata type
f(`{"streams":[{"values":[["1577836800000000001", "foo bar", ["metadata_1", "md_value"]]]}]}`)
// structured metadata with unexpected value type
f(`{"streams":[{"values":[["1577836800000000001", "foo bar", {"metadata_1": 1}]] }]}`)
}
func TestParseJSONRequest_Success(t *testing.T) {
f := func(s string, timestampsExpected []int64, resultExpected string) {
t.Helper()
tlp := &insertutil.TestLogMessageProcessor{}
if err := parseJSONRequest([]byte(s), tlp, nil, false, false); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if err := tlp.Verify(timestampsExpected, resultExpected); err != nil {
t.Fatal(err)
}
}
// Empty streams
f(`{"streams":[]}`, nil, ``)
f(`{"streams":[{"values":[]}]}`, nil, ``)
f(`{"streams":[{"stream":{},"values":[]}]}`, nil, ``)
f(`{"streams":[{"stream":{"foo":"bar"},"values":[]}]}`, nil, ``)
// Empty stream labels
f(`{"streams":[{"values":[["1577836800000000001", "foo bar"]]}]}`, []int64{1577836800000000001}, `{"_msg":"foo bar"}`)
f(`{"streams":[{"stream":{},"values":[["1577836800000000001", "foo bar"]]}]}`, []int64{1577836800000000001}, `{"_msg":"foo bar"}`)
// Non-empty stream labels
f(`{"streams":[{"stream":{
"label1": "value1",
"label2": "value2"
},"values":[
["1577836800000000001", "foo bar"],
["1686026123.62", "abc"],
["147.78369e9", "foobar"]
]}]}`, []int64{1577836800000000001, 1686026123620000000, 147783690000000000}, `{"label1":"value1","label2":"value2","_msg":"foo bar"}
{"label1":"value1","label2":"value2","_msg":"abc"}
{"label1":"value1","label2":"value2","_msg":"foobar"}`)
// Multiple streams
f(`{
"streams": [
{
"stream": {
"foo": "bar",
"a": "b"
},
"values": [
["1577836800000000001", "foo bar"],
["1577836900005000002", "abc"]
]
},
{
"stream": {
"x": "y"
},
"values": [
["1877836900005000002", "yx"]
]
}
]
}`, []int64{1577836800000000001, 1577836900005000002, 1877836900005000002}, `{"foo":"bar","a":"b","_msg":"foo bar"}
{"foo":"bar","a":"b","_msg":"abc"}
{"x":"y","_msg":"yx"}`)
// values with metadata
f(`{"streams":[{"values":[["1577836800000000001", "foo bar", {"metadata_1": "md_value"}]]}]}`, []int64{1577836800000000001}, `{"metadata_1":"md_value","_msg":"foo bar"}`)
f(`{"streams":[{"values":[["1577836800000000001", "foo bar", {}]]}]}`, []int64{1577836800000000001}, `{"_msg":"foo bar"}`)
}
func TestParseJSONRequest_ParseMessage(t *testing.T) {
f := func(s string, msgFields []string, timestampsExpected []int64, resultExpected string) {
t.Helper()
tlp := &insertutil.TestLogMessageProcessor{}
if err := parseJSONRequest([]byte(s), tlp, msgFields, false, true); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if err := tlp.Verify(timestampsExpected, resultExpected); err != nil {
t.Fatal(err)
}
}
f(`{
"streams": [
{
"stream": {
"foo": "bar",
"a": "b"
},
"values": [
["1577836800000000001", "{\"user_id\":\"123\"}"],
["1577836900005000002", "abc", {"trace_id":"pqw"}],
["1577836900005000003", "{def}"]
]
},
{
"stream": {
"x": "y"
},
"values": [
["1877836900005000004", "{\"trace_id\":\"111\",\"parent_id\":\"abc\"}"]
]
}
]
}`, []string{"a", "trace_id"}, []int64{1577836800000000001, 1577836900005000002, 1577836900005000003, 1877836900005000004}, `{"foo":"bar","a":"b","user_id":"123"}
{"foo":"bar","a":"b","trace_id":"pqw","_msg":"abc"}
{"foo":"bar","a":"b","_msg":"{def}"}
{"x":"y","_msg":"111","parent_id":"abc"}`)
}

View File

@@ -1,78 +0,0 @@
package loki
import (
"fmt"
"strconv"
"testing"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
)
func BenchmarkParseJSONRequest(b *testing.B) {
for _, streams := range []int{5, 10} {
for _, rows := range []int{100, 1000} {
for _, labels := range []int{10, 50} {
b.Run(fmt.Sprintf("streams_%d/rows_%d/labels_%d", streams, rows, labels), func(b *testing.B) {
benchmarkParseJSONRequest(b, streams, rows, labels)
})
}
}
}
}
func benchmarkParseJSONRequest(b *testing.B, streams, rows, labels int) {
blp := &insertutil.BenchmarkLogMessageProcessor{}
b.ReportAllocs()
b.SetBytes(int64(streams * rows))
b.RunParallel(func(pb *testing.PB) {
data := getJSONBody(streams, rows, labels)
for pb.Next() {
if err := parseJSONRequest(data, blp, nil, false, true); err != nil {
panic(fmt.Errorf("unexpected error: %w", err))
}
}
})
}
func getJSONBody(streams, rows, labels int) []byte {
body := append([]byte{}, `{"streams":[`...)
now := time.Now().UnixNano()
valuePrefix := fmt.Sprintf(`["%d","value_`, now)
for i := 0; i < streams; i++ {
body = append(body, `{"stream":{`...)
for j := 0; j < labels; j++ {
body = append(body, `"label_`...)
body = strconv.AppendInt(body, int64(j), 10)
body = append(body, `":"value_`...)
body = strconv.AppendInt(body, int64(j), 10)
body = append(body, '"')
if j < labels-1 {
body = append(body, ',')
}
}
body = append(body, `}, "values":[`...)
for j := 0; j < rows; j++ {
body = append(body, valuePrefix...)
body = strconv.AppendInt(body, int64(j), 10)
body = append(body, `"]`...)
if j < rows-1 {
body = append(body, ',')
}
}
body = append(body, `]}`...)
if i < streams-1 {
body = append(body, ',')
}
}
body = append(body, `]}`...)
return body
}

View File

@@ -1,219 +0,0 @@
package loki
import (
"fmt"
"net/http"
"strconv"
"strings"
"sync"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/protoparserutil"
"github.com/VictoriaMetrics/metrics"
)
var (
pushReqsPool sync.Pool
)
func handleProtobuf(r *http.Request, w http.ResponseWriter) {
startTime := time.Now()
requestsProtobufTotal.Inc()
cp, err := getCommonParams(r)
if err != nil {
httpserver.Errorf(w, r, "cannot parse common params from request: %s", err)
return
}
if err := vlstorage.CanWriteData(); err != nil {
httpserver.Errorf(w, r, "%s", err)
return
}
encoding := r.Header.Get("Content-Encoding")
if encoding == "" {
// Loki protocol uses snappy compression by default.
// See https://grafana.com/docs/loki/latest/reference/loki-http-api/#ingest-logs
encoding = "snappy"
}
err = protoparserutil.ReadUncompressedData(r.Body, encoding, maxRequestSize, func(data []byte) error {
lmp := cp.cp.NewLogMessageProcessor("loki_protobuf", false)
useDefaultStreamFields := len(cp.cp.StreamFields) == 0
err := parseProtobufRequest(data, lmp, cp.cp.MsgFields, useDefaultStreamFields, cp.parseMessage)
lmp.MustClose()
return err
})
if err != nil {
httpserver.Errorf(w, r, "cannot read Loki protobuf data: %s", err)
return
}
// update requestProtobufDuration only for successfully parsed requests
// There is no need in updating requestProtobufDuration for request errors,
// since their timings are usually much smaller than the timing for successful request parsing.
requestProtobufDuration.UpdateDuration(startTime)
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8505
w.WriteHeader(http.StatusNoContent)
}
var (
requestsProtobufTotal = metrics.NewCounter(`vl_http_requests_total{path="/insert/loki/api/v1/push",format="protobuf"}`)
requestProtobufDuration = metrics.NewHistogram(`vl_http_request_duration_seconds{path="/insert/loki/api/v1/push",format="protobuf"}`)
)
func parseProtobufRequest(data []byte, lmp insertutil.LogMessageProcessor, msgFields []string, useDefaultStreamFields, parseMessage bool) error {
req := getPushRequest()
defer putPushRequest(req)
err := req.UnmarshalProtobuf(data)
if err != nil {
return fmt.Errorf("cannot parse request body: %w", err)
}
fields := getFields()
defer putFields(fields)
var msgParser *logstorage.JSONParser
if parseMessage {
msgParser = logstorage.GetJSONParser()
defer logstorage.PutJSONParser(msgParser)
}
streams := req.Streams
currentTimestamp := time.Now().UnixNano()
for i := range streams {
stream := &streams[i]
// st.Labels contains labels for the stream.
// Labels are same for all entries in the stream.
fields.fields, err = parsePromLabels(fields.fields[:0], stream.Labels)
if err != nil {
return fmt.Errorf("cannot parse stream labels %q: %w", stream.Labels, err)
}
commonFieldsLen := len(fields.fields)
entries := stream.Entries
for j := range entries {
e := &entries[j]
fields.fields = fields.fields[:commonFieldsLen]
for _, lp := range e.StructuredMetadata {
fields.fields = append(fields.fields, logstorage.Field{
Name: lp.Name,
Value: lp.Value,
})
}
allowMsgRenaming := false
fields.fields, allowMsgRenaming = addMsgField(fields.fields, msgParser, e.Line)
ts := e.Timestamp.UnixNano()
if ts == 0 {
ts = currentTimestamp
}
var streamFields []logstorage.Field
if useDefaultStreamFields {
streamFields = fields.fields[:commonFieldsLen]
}
if allowMsgRenaming {
logstorage.RenameField(fields.fields[commonFieldsLen:], msgFields, "_msg")
}
lmp.AddRow(ts, fields.fields, streamFields)
}
}
return nil
}
func getFields() *fields {
v := fieldsPool.Get()
if v == nil {
return &fields{}
}
return v.(*fields)
}
func putFields(f *fields) {
f.fields = f.fields[:0]
fieldsPool.Put(f)
}
var fieldsPool sync.Pool
type fields struct {
fields []logstorage.Field
}
// parsePromLabels parses log fields in Prometheus text exposition format from s, appends them to dst and returns the result.
//
// See test data of promtail for examples: https://github.com/grafana/loki/blob/a24ef7b206e0ca63ee74ca6ecb0a09b745cd2258/pkg/push/types_test.go
func parsePromLabels(dst []logstorage.Field, s string) ([]logstorage.Field, error) {
// Make sure s is wrapped into `{...}`
s = strings.TrimSpace(s)
if len(s) < 2 {
return nil, fmt.Errorf("too short string to parse: %q", s)
}
if s[0] != '{' {
return nil, fmt.Errorf("missing `{` at the beginning of %q", s)
}
if s[len(s)-1] != '}' {
return nil, fmt.Errorf("missing `}` at the end of %q", s)
}
s = s[1 : len(s)-1]
for len(s) > 0 {
// Parse label name
n := strings.IndexByte(s, '=')
if n < 0 {
return nil, fmt.Errorf("cannot find `=` char for label value at %s", s)
}
name := s[:n]
s = s[n+1:]
// Parse label value
qs, err := strconv.QuotedPrefix(s)
if err != nil {
return nil, fmt.Errorf("cannot parse value for label %q at %s: %w", name, s, err)
}
s = s[len(qs):]
value, err := strconv.Unquote(qs)
if err != nil {
return nil, fmt.Errorf("cannot unquote value %q for label %q: %w", qs, name, err)
}
// Append the found field to dst.
dst = append(dst, logstorage.Field{
Name: name,
Value: value,
})
// Check whether there are other labels remaining
if len(s) == 0 {
break
}
if !strings.HasPrefix(s, ",") {
return nil, fmt.Errorf("missing `,` char at %s", s)
}
s = s[1:]
s = strings.TrimPrefix(s, " ")
}
return dst, nil
}
func getPushRequest() *PushRequest {
v := pushReqsPool.Get()
if v == nil {
return &PushRequest{}
}
return v.(*PushRequest)
}
func putPushRequest(req *PushRequest) {
req.reset()
pushReqsPool.Put(req)
}

View File

@@ -1,218 +0,0 @@
package loki
import (
"fmt"
"strings"
"testing"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
)
type testLogMessageProcessor struct {
pr PushRequest
}
func (tlp *testLogMessageProcessor) AddRow(timestamp int64, fields, streamFields []logstorage.Field) {
if streamFields != nil {
panic(fmt.Errorf("unexpected non-nil streamFields: %v", streamFields))
}
msg := ""
for _, f := range fields {
if f.Name == "_msg" {
msg = f.Value
}
}
var a []string
for _, f := range fields {
if f.Name == "_msg" {
continue
}
item := fmt.Sprintf("%s=%q", f.Name, f.Value)
a = append(a, item)
}
labels := "{" + strings.Join(a, ", ") + "}"
tlp.pr.Streams = append(tlp.pr.Streams, Stream{
Labels: labels,
Entries: []Entry{
{
Timestamp: time.Unix(0, timestamp),
Line: strings.Clone(msg),
},
},
})
}
func (tlp *testLogMessageProcessor) MustClose() {
}
func TestParseProtobufRequest_Success(t *testing.T) {
f := func(s string, timestampsExpected []int64, resultExpected string) {
t.Helper()
tlp := &testLogMessageProcessor{}
if err := parseJSONRequest([]byte(s), tlp, nil, false, false); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if len(tlp.pr.Streams) != len(timestampsExpected) {
t.Fatalf("unexpected number of streams; got %d; want %d", len(tlp.pr.Streams), len(timestampsExpected))
}
data := tlp.pr.MarshalProtobuf(nil)
tlp2 := &insertutil.TestLogMessageProcessor{}
if err := parseProtobufRequest(data, tlp2, nil, false, false); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if err := tlp2.Verify(timestampsExpected, resultExpected); err != nil {
t.Fatal(err)
}
}
// Empty streams
f(`{"streams":[]}`, nil, ``)
f(`{"streams":[{"values":[]}]}`, nil, ``)
f(`{"streams":[{"stream":{},"values":[]}]}`, nil, ``)
f(`{"streams":[{"stream":{"foo":"bar"},"values":[]}]}`, nil, ``)
// Empty stream labels
f(`{"streams":[{"values":[["1577836800000000001", "foo bar"]]}]}`, []int64{1577836800000000001}, `{"_msg":"foo bar"}`)
f(`{"streams":[{"stream":{},"values":[["1577836800000000001", "foo bar"]]}]}`, []int64{1577836800000000001}, `{"_msg":"foo bar"}`)
// Non-empty stream labels
f(`{"streams":[{"stream":{
"label1": "value1",
"label2": "value2"
},"values":[
["1577836800000000001", "foo bar"],
["1477836900005000002", "abc"],
["147.78369e9", "foobar"]
]}]}`, []int64{1577836800000000001, 1477836900005000002, 147783690000000000}, `{"label1":"value1","label2":"value2","_msg":"foo bar"}
{"label1":"value1","label2":"value2","_msg":"abc"}
{"label1":"value1","label2":"value2","_msg":"foobar"}`)
// Multiple streams
f(`{
"streams": [
{
"stream": {
"foo": "bar",
"a": "b"
},
"values": [
["1577836800000000001", "foo bar"],
["1577836900005000002", "abc"]
]
},
{
"stream": {
"x": "y"
},
"values": [
["1877836900005000002", "yx"]
]
}
]
}`, []int64{1577836800000000001, 1577836900005000002, 1877836900005000002}, `{"foo":"bar","a":"b","_msg":"foo bar"}
{"foo":"bar","a":"b","_msg":"abc"}
{"x":"y","_msg":"yx"}`)
}
func TestParseProtobufRequest_ParseMessage(t *testing.T) {
f := func(s string, msgFields []string, timestampsExpected []int64, resultExpected string) {
t.Helper()
tlp := &testLogMessageProcessor{}
if err := parseJSONRequest([]byte(s), tlp, nil, false, false); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if len(tlp.pr.Streams) != len(timestampsExpected) {
t.Fatalf("unexpected number of streams; got %d; want %d", len(tlp.pr.Streams), len(timestampsExpected))
}
data := tlp.pr.MarshalProtobuf(nil)
tlp2 := &insertutil.TestLogMessageProcessor{}
if err := parseProtobufRequest(data, tlp2, msgFields, false, true); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if err := tlp2.Verify(timestampsExpected, resultExpected); err != nil {
t.Fatal(err)
}
}
f(`{
"streams": [
{
"stream": {
"foo": "bar",
"a": "b"
},
"values": [
["1577836800000000001", "{\"user_id\":\"123\"}"],
["1577836900005000002", "abc", {"trace_id":"pqw"}],
["1577836900005000003", "{def}"]
]
},
{
"stream": {
"x": "y"
},
"values": [
["1877836900005000004", "{\"trace_id\":\"432\",\"parent_id\":\"qwerty\"}"]
]
}
]
}`, []string{"a", "trace_id"}, []int64{1577836800000000001, 1577836900005000002, 1577836900005000003, 1877836900005000004}, `{"foo":"bar","a":"b","user_id":"123"}
{"foo":"bar","a":"b","trace_id":"pqw","_msg":"abc"}
{"foo":"bar","a":"b","_msg":"{def}"}
{"x":"y","_msg":"432","parent_id":"qwerty"}`)
}
func TestParsePromLabels_Success(t *testing.T) {
f := func(s string) {
t.Helper()
fields, err := parsePromLabels(nil, s)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
var a []string
for _, f := range fields {
a = append(a, fmt.Sprintf("%s=%q", f.Name, f.Value))
}
result := "{" + strings.Join(a, ", ") + "}"
if result != s {
t.Fatalf("unexpected result;\ngot\n%s\nwant\n%s", result, s)
}
}
f("{}")
f(`{foo="bar"}`)
f(`{foo="bar", baz="x", y="z"}`)
f(`{foo="ba\"r\\z\n", a="", b="\"\\"}`)
}
func TestParsePromLabels_Failure(t *testing.T) {
f := func(s string) {
t.Helper()
fields, err := parsePromLabels(nil, s)
if err == nil {
t.Fatalf("expecting non-nil error")
}
if len(fields) > 0 {
t.Fatalf("unexpected non-empty fields: %s", fields)
}
}
f("")
f("{")
f(`{foo}`)
f(`{foo=bar}`)
f(`{foo="bar}`)
f(`{foo="ba\",r}`)
f(`{foo="bar" baz="aa"}`)
f(`foobar`)
f(`foo{bar="baz"}`)
}

View File

@@ -1,80 +0,0 @@
package loki
import (
"fmt"
"strconv"
"testing"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
)
func BenchmarkParseProtobufRequest(b *testing.B) {
for _, streams := range []int{5, 10} {
for _, rows := range []int{100, 1000} {
for _, labels := range []int{10, 50} {
b.Run(fmt.Sprintf("streams_%d/rows_%d/labels_%d", streams, rows, labels), func(b *testing.B) {
benchmarkParseProtobufRequest(b, streams, rows, labels)
})
}
}
}
}
func benchmarkParseProtobufRequest(b *testing.B, streams, rows, labels int) {
blp := &insertutil.BenchmarkLogMessageProcessor{}
b.ReportAllocs()
b.SetBytes(int64(streams * rows))
b.RunParallel(func(pb *testing.PB) {
body := getProtobufBody(streams, rows, labels)
for pb.Next() {
if err := parseProtobufRequest(body, blp, nil, false, true); err != nil {
panic(fmt.Errorf("unexpected error: %w", err))
}
}
})
}
func getProtobufBody(streamsCount, rowsCount, labelsCount int) []byte {
var b []byte
var entries []Entry
streams := make([]Stream, streamsCount)
for i := range streams {
b = b[:0]
b = append(b, '{')
for j := 0; j < labelsCount; j++ {
b = append(b, "label_"...)
b = strconv.AppendInt(b, int64(j), 10)
b = append(b, `="value_`...)
b = strconv.AppendInt(b, int64(j), 10)
b = append(b, '"')
if j < labelsCount-1 {
b = append(b, ',')
}
}
b = append(b, '}')
labels := string(b)
var rowsBuf []byte
entriesLen := len(entries)
for j := 0; j < rowsCount; j++ {
rowsBufLen := len(rowsBuf)
rowsBuf = append(rowsBuf, "value_"...)
rowsBuf = strconv.AppendInt(rowsBuf, int64(j), 10)
entries = append(entries, Entry{
Timestamp: time.Now(),
Line: bytesutil.ToUnsafeString(rowsBuf[rowsBufLen:]),
})
}
st := &streams[i]
st.Labels = labels
st.Entries = entries[entriesLen:]
}
pr := PushRequest{
Streams: streams,
}
return pr.MarshalProtobuf(nil)
}

View File

@@ -1,302 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: push_request.proto
// source: https://raw.githubusercontent.com/grafana/loki/main/pkg/push/push_request.proto
// Licensed under the Apache License, Version 2.0 (the "License");
// https://github.com/grafana/loki/blob/main/pkg/push/LICENSE
package loki
import (
"fmt"
"time"
"github.com/VictoriaMetrics/easyproto"
)
var mp easyproto.MarshalerPool
// PushRequest represents Loki PushRequest
//
// See https://github.com/grafana/loki/blob/ada4b7b8713385fbe9f5984a5a0aaaddf1a7b851/pkg/push/push.proto#L14
type PushRequest struct {
Streams []Stream
entriesBuf []Entry
labelPairBuf []LabelPair
}
func (pr *PushRequest) reset() {
pr.Streams = pr.Streams[:0]
pr.entriesBuf = pr.entriesBuf[:0]
pr.labelPairBuf = pr.labelPairBuf[:0]
}
// UnmarshalProtobuf unmarshals pr from protobuf message at src.
//
// pr remains valid until src is modified.
func (pr *PushRequest) UnmarshalProtobuf(src []byte) error {
pr.reset()
var err error
pr.entriesBuf, pr.labelPairBuf, err = pr.unmarshalProtobuf(pr.entriesBuf, pr.labelPairBuf, src)
return err
}
// MarshalProtobuf marshals r to protobuf message, appends it to dst and returns the result.
func (pr *PushRequest) MarshalProtobuf(dst []byte) []byte {
m := mp.Get()
pr.marshalProtobuf(m.MessageMarshaler())
dst = m.Marshal(dst)
mp.Put(m)
return dst
}
func (pr *PushRequest) marshalProtobuf(mm *easyproto.MessageMarshaler) {
for _, s := range pr.Streams {
s.marshalProtobuf(mm.AppendMessage(1))
}
}
func (pr *PushRequest) unmarshalProtobuf(entriesBuf []Entry, labelPairBuf []LabelPair, src []byte) ([]Entry, []LabelPair, error) {
// message PushRequest {
// repeated Stream streams = 1;
// }
var err error
var fc easyproto.FieldContext
for len(src) > 0 {
src, err = fc.NextField(src)
if err != nil {
return entriesBuf, labelPairBuf, fmt.Errorf("cannot read next field in PushRequest: %w", err)
}
switch fc.FieldNum {
case 1:
data, ok := fc.MessageData()
if !ok {
return entriesBuf, labelPairBuf, fmt.Errorf("cannot read Stream data")
}
pr.Streams = append(pr.Streams, Stream{})
s := &pr.Streams[len(pr.Streams)-1]
entriesBuf, labelPairBuf, err = s.unmarshalProtobuf(entriesBuf, labelPairBuf, data)
if err != nil {
return entriesBuf, labelPairBuf, fmt.Errorf("cannot unmarshal Stream: %w", err)
}
}
}
return entriesBuf, labelPairBuf, nil
}
// Stream represents Loki stream.
//
// See https://github.com/grafana/loki/blob/ada4b7b8713385fbe9f5984a5a0aaaddf1a7b851/pkg/push/push.proto#L23
type Stream struct {
Labels string
Entries []Entry
}
func (s *Stream) marshalProtobuf(mm *easyproto.MessageMarshaler) {
mm.AppendString(1, s.Labels)
for _, e := range s.Entries {
e.marshalProtobuf(mm.AppendMessage(2))
}
}
func (s *Stream) unmarshalProtobuf(entriesBuf []Entry, labelPairBuf []LabelPair, src []byte) ([]Entry, []LabelPair, error) {
// message Stream {
// string labels = 1;
// repeated Entry entries = 2;
// }
var err error
var fc easyproto.FieldContext
entriesBufLen := len(entriesBuf)
for len(src) > 0 {
src, err = fc.NextField(src)
if err != nil {
return entriesBuf, labelPairBuf, fmt.Errorf("cannot read next field in Stream: %w", err)
}
switch fc.FieldNum {
case 1:
labels, ok := fc.String()
if !ok {
return entriesBuf, labelPairBuf, fmt.Errorf("cannot read labels")
}
s.Labels = labels
case 2:
data, ok := fc.MessageData()
if !ok {
return entriesBuf, labelPairBuf, fmt.Errorf("cannot read Entry data")
}
entriesBuf = append(entriesBuf, Entry{})
e := &entriesBuf[len(entriesBuf)-1]
labelPairBuf, err = e.unmarshalProtobuf(labelPairBuf, data)
if err != nil {
return entriesBuf, labelPairBuf, fmt.Errorf("cannot unmarshal Entry: %w", err)
}
}
}
s.Entries = entriesBuf[entriesBufLen:]
return entriesBuf, labelPairBuf, nil
}
// Entry represents Loki entry.
//
// See https://github.com/grafana/loki/blob/ada4b7b8713385fbe9f5984a5a0aaaddf1a7b851/pkg/push/push.proto#L38
type Entry struct {
Timestamp time.Time
Line string
StructuredMetadata []LabelPair
}
func (e *Entry) marshalProtobuf(mm *easyproto.MessageMarshaler) {
marshalTime(mm, 1, e.Timestamp)
mm.AppendString(2, e.Line)
for _, lp := range e.StructuredMetadata {
lp.marshalProtobuf(mm.AppendMessage(3))
}
}
func (e *Entry) unmarshalProtobuf(labelPairBuf []LabelPair, src []byte) ([]LabelPair, error) {
// message Entry {
// Timestamp timestamp = 1;
// string line = 2;
// repeated LabelPair structuredMetadata = 3;
// }
var err error
var fc easyproto.FieldContext
labelPairBufLen := len(labelPairBuf)
for len(src) > 0 {
src, err = fc.NextField(src)
if err != nil {
return labelPairBuf, fmt.Errorf("cannot read next field in Entry: %w", err)
}
switch fc.FieldNum {
case 1:
data, ok := fc.MessageData()
if !ok {
return labelPairBuf, fmt.Errorf("cannot read Timestamp data")
}
timestamp, err := unmarshalTime(data)
if err != nil {
return labelPairBuf, fmt.Errorf("cannot unmarshal Timestamp: %w", err)
}
e.Timestamp = timestamp
case 2:
line, ok := fc.String()
if !ok {
return labelPairBuf, fmt.Errorf("cannot read Line")
}
e.Line = line
case 3:
data, ok := fc.MessageData()
if !ok {
return labelPairBuf, fmt.Errorf("cannot read StructuredMetadata")
}
labelPairBuf = append(labelPairBuf, LabelPair{})
lp := &labelPairBuf[len(labelPairBuf)-1]
if err := lp.unmarshalProtobuf(data); err != nil {
return labelPairBuf, fmt.Errorf("cannot unmarshal StructuredMetadata: %w", err)
}
}
}
e.StructuredMetadata = labelPairBuf[labelPairBufLen:]
return labelPairBuf, nil
}
// LabelPair represents Loki label pair.
//
// See https://github.com/grafana/loki/blob/ada4b7b8713385fbe9f5984a5a0aaaddf1a7b851/pkg/push/push.proto#L33
type LabelPair struct {
Name string
Value string
}
func (lp *LabelPair) marshalProtobuf(mm *easyproto.MessageMarshaler) {
mm.AppendString(1, lp.Name)
mm.AppendString(2, lp.Value)
}
func (lp *LabelPair) unmarshalProtobuf(src []byte) (err error) {
// message LabelPair {
// string name = 1;
// string value = 2;
// }
var fc easyproto.FieldContext
for len(src) > 0 {
src, err = fc.NextField(src)
if err != nil {
return fmt.Errorf("cannot read next field in LabelPair: %w", err)
}
switch fc.FieldNum {
case 1:
name, ok := fc.String()
if !ok {
return fmt.Errorf("cannot read name")
}
lp.Name = name
case 2:
value, ok := fc.String()
if !ok {
return fmt.Errorf("cannot unmarshal value")
}
lp.Value = value
}
}
return nil
}
func marshalTime(mm *easyproto.MessageMarshaler, fieldNum uint32, timestamp time.Time) {
nsecs := timestamp.UnixNano()
ts := Timestamp{
Seconds: nsecs / 1e9,
Nanos: int32(nsecs % 1e9),
}
ts.marshalProtobuf(mm.AppendMessage(fieldNum))
}
func unmarshalTime(src []byte) (time.Time, error) {
var ts Timestamp
if err := ts.unmarshalProtobuf(src); err != nil {
return time.Time{}, err
}
timestamp := time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
return timestamp, nil
}
// Timestamp is protobuf well-known timestamp type.
type Timestamp struct {
Seconds int64
Nanos int32
}
func (ts *Timestamp) marshalProtobuf(mm *easyproto.MessageMarshaler) {
mm.AppendInt64(1, ts.Seconds)
mm.AppendInt32(2, ts.Nanos)
}
func (ts *Timestamp) unmarshalProtobuf(src []byte) (err error) {
// message Timestamp {
// int64 seconds = 1;
// int32 nanos = 2;
// }
var fc easyproto.FieldContext
for len(src) > 0 {
src, err = fc.NextField(src)
if err != nil {
return fmt.Errorf("cannot read next field in Timestamp: %w", err)
}
switch fc.FieldNum {
case 1:
seconds, ok := fc.Int64()
if !ok {
return fmt.Errorf("cannot read Seconds")
}
ts.Seconds = seconds
case 2:
nanos, ok := fc.Int32()
if !ok {
return fmt.Errorf("cannot read Nanos")
}
ts.Nanos = nanos
}
}
return nil
}

View File

@@ -1,69 +0,0 @@
package vlinsert
import (
"fmt"
"net/http"
"strings"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/datadog"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/elasticsearch"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/journald"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/jsonline"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/loki"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/opentelemetry"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/syslog"
)
// Init initializes vlinsert
func Init() {
syslog.MustInit()
}
// Stop stops vlinsert
func Stop() {
syslog.MustStop()
}
// RequestHandler handles insert requests for VictoriaLogs
func RequestHandler(w http.ResponseWriter, r *http.Request) bool {
path := r.URL.Path
if !strings.HasPrefix(path, "/insert/") {
// Skip requests, which do not start with /insert/, since these aren't our requests.
return false
}
path = strings.TrimPrefix(path, "/insert")
path = strings.ReplaceAll(path, "//", "/")
switch path {
case "/jsonline":
jsonline.RequestHandler(w, r)
return true
case "/ready":
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
fmt.Fprintf(w, `{"status":"ok"}`)
return true
}
switch {
case strings.HasPrefix(path, "/elasticsearch"):
// some clients may omit trailing slash
// see https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8353
path = strings.TrimPrefix(path, "/elasticsearch")
return elasticsearch.RequestHandler(path, w, r)
case strings.HasPrefix(path, "/loki/"):
path = strings.TrimPrefix(path, "/loki")
return loki.RequestHandler(path, w, r)
case strings.HasPrefix(path, "/opentelemetry/"):
path = strings.TrimPrefix(path, "/opentelemetry")
return opentelemetry.RequestHandler(path, w, r)
case strings.HasPrefix(path, "/journald/"):
path = strings.TrimPrefix(path, "/journald")
return journald.RequestHandler(path, w, r)
case strings.HasPrefix(path, "/datadog/"):
path = strings.TrimPrefix(path, "/datadog")
return datadog.RequestHandler(path, w, r)
default:
return false
}
}

View File

@@ -1,140 +0,0 @@
package opentelemetry
import (
"fmt"
"net/http"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/opentelemetry/pb"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/protoparserutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/slicesutil"
"github.com/VictoriaMetrics/metrics"
)
var maxRequestSize = flagutil.NewBytes("opentelemetry.maxRequestSize", 64*1024*1024, "The maximum size in bytes of a single OpenTelemetry request")
// RequestHandler processes Opentelemetry insert requests
func RequestHandler(path string, w http.ResponseWriter, r *http.Request) bool {
switch path {
// use the same path as opentelemetry collector
// https://opentelemetry.io/docs/specs/otlp/#otlphttp-request
case "/v1/logs":
if r.Header.Get("Content-Type") == "application/json" {
httpserver.Errorf(w, r, "json encoding isn't supported for opentelemetry format. Use protobuf encoding")
return true
}
handleProtobuf(r, w)
return true
default:
return false
}
}
func handleProtobuf(r *http.Request, w http.ResponseWriter) {
startTime := time.Now()
requestsProtobufTotal.Inc()
cp, err := insertutil.GetCommonParams(r)
if err != nil {
httpserver.Errorf(w, r, "cannot parse common params from request: %s", err)
return
}
if err := vlstorage.CanWriteData(); err != nil {
httpserver.Errorf(w, r, "%s", err)
return
}
encoding := r.Header.Get("Content-Encoding")
err = protoparserutil.ReadUncompressedData(r.Body, encoding, maxRequestSize, func(data []byte) error {
lmp := cp.NewLogMessageProcessor("opentelelemtry_protobuf", false)
useDefaultStreamFields := len(cp.StreamFields) == 0
err := pushProtobufRequest(data, lmp, useDefaultStreamFields)
lmp.MustClose()
return err
})
if err != nil {
httpserver.Errorf(w, r, "cannot read OpenTelemetry protocol data: %s", err)
return
}
// update requestProtobufDuration only for successfully parsed requests
// There is no need in updating requestProtobufDuration for request errors,
// since their timings are usually much smaller than the timing for successful request parsing.
requestProtobufDuration.UpdateDuration(startTime)
}
var (
requestsProtobufTotal = metrics.NewCounter(`vl_http_requests_total{path="/insert/opentelemetry/v1/logs",format="protobuf"}`)
errorsTotal = metrics.NewCounter(`vl_http_errors_total{path="/insert/opentelemetry/v1/logs",format="protobuf"}`)
requestProtobufDuration = metrics.NewHistogram(`vl_http_request_duration_seconds{path="/insert/opentelemetry/v1/logs",format="protobuf"}`)
)
func pushProtobufRequest(data []byte, lmp insertutil.LogMessageProcessor, useDefaultStreamFields bool) error {
var req pb.ExportLogsServiceRequest
if err := req.UnmarshalProtobuf(data); err != nil {
errorsTotal.Inc()
return fmt.Errorf("cannot unmarshal request from %d bytes: %w", len(data), err)
}
var commonFields []logstorage.Field
for _, rl := range req.ResourceLogs {
attributes := rl.Resource.Attributes
commonFields = slicesutil.SetLength(commonFields, len(attributes))
for i, attr := range attributes {
commonFields[i].Name = attr.Key
commonFields[i].Value = attr.Value.FormatString(true)
}
commonFieldsLen := len(commonFields)
for _, sc := range rl.ScopeLogs {
commonFields = pushFieldsFromScopeLogs(&sc, commonFields[:commonFieldsLen], lmp, useDefaultStreamFields)
}
}
return nil
}
func pushFieldsFromScopeLogs(sc *pb.ScopeLogs, commonFields []logstorage.Field, lmp insertutil.LogMessageProcessor, useDefaultStreamFields bool) []logstorage.Field {
fields := commonFields
for _, lr := range sc.LogRecords {
fields = fields[:len(commonFields)]
fields = append(fields, logstorage.Field{
Name: "_msg",
Value: lr.Body.FormatString(true),
})
for _, attr := range lr.Attributes {
fields = append(fields, logstorage.Field{
Name: attr.Key,
Value: attr.Value.FormatString(true),
})
}
if len(lr.TraceID) > 0 {
fields = append(fields, logstorage.Field{
Name: "trace_id",
Value: lr.TraceID,
})
}
if len(lr.SpanID) > 0 {
fields = append(fields, logstorage.Field{
Name: "span_id",
Value: lr.SpanID,
})
}
fields = append(fields, logstorage.Field{
Name: "severity",
Value: lr.FormatSeverity(),
})
var streamFields []logstorage.Field
if useDefaultStreamFields {
streamFields = commonFields
}
lmp.AddRow(lr.ExtractTimestampNano(), fields, streamFields)
}
return fields
}

View File

@@ -1,131 +0,0 @@
package opentelemetry
import (
"testing"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/opentelemetry/pb"
)
func TestPushProtoOk(t *testing.T) {
f := func(src []pb.ResourceLogs, timestampsExpected []int64, resultExpected string) {
t.Helper()
lr := pb.ExportLogsServiceRequest{
ResourceLogs: src,
}
pData := lr.MarshalProtobuf(nil)
tlp := &insertutil.TestLogMessageProcessor{}
if err := pushProtobufRequest(pData, tlp, false); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if err := tlp.Verify(timestampsExpected, resultExpected); err != nil {
t.Fatal(err)
}
}
// single line without resource attributes
f([]pb.ResourceLogs{
{
ScopeLogs: []pb.ScopeLogs{
{
LogRecords: []pb.LogRecord{
{Attributes: []*pb.KeyValue{}, TimeUnixNano: 1234, SeverityNumber: 1, Body: pb.AnyValue{StringValue: ptrTo("log-line-message")}},
},
},
},
},
},
[]int64{1234},
`{"_msg":"log-line-message","severity":"Trace"}`,
)
// multi-line with resource attributes
f([]pb.ResourceLogs{
{
Resource: pb.Resource{
Attributes: []*pb.KeyValue{
{Key: "logger", Value: &pb.AnyValue{StringValue: ptrTo("context")}},
{Key: "instance_id", Value: &pb.AnyValue{IntValue: ptrTo[int64](10)}},
{Key: "node_taints", Value: &pb.AnyValue{KeyValueList: &pb.KeyValueList{
Values: []*pb.KeyValue{
{Key: "role", Value: &pb.AnyValue{StringValue: ptrTo("dev")}},
{Key: "cluster_load_percent", Value: &pb.AnyValue{DoubleValue: ptrTo(0.55)}},
},
}}},
},
},
ScopeLogs: []pb.ScopeLogs{
{
LogRecords: []pb.LogRecord{
{Attributes: []*pb.KeyValue{}, TimeUnixNano: 1234, SeverityNumber: 1, Body: pb.AnyValue{StringValue: ptrTo("log-line-message")}},
{Attributes: []*pb.KeyValue{}, TimeUnixNano: 1235, SeverityNumber: 21, Body: pb.AnyValue{StringValue: ptrTo("log-line-message-msg-2")}},
{Attributes: []*pb.KeyValue{}, TimeUnixNano: 1236, SeverityNumber: -1, Body: pb.AnyValue{StringValue: ptrTo("log-line-message-msg-2")}},
},
},
},
},
},
[]int64{1234, 1235, 1236},
`{"logger":"context","instance_id":"10","node_taints":"{\"role\":\"dev\",\"cluster_load_percent\":0.55}","_msg":"log-line-message","severity":"Trace"}
{"logger":"context","instance_id":"10","node_taints":"{\"role\":\"dev\",\"cluster_load_percent\":0.55}","_msg":"log-line-message-msg-2","severity":"Unspecified"}
{"logger":"context","instance_id":"10","node_taints":"{\"role\":\"dev\",\"cluster_load_percent\":0.55}","_msg":"log-line-message-msg-2","severity":"Unspecified"}`,
)
// multi-scope with resource attributes and multi-line
f([]pb.ResourceLogs{
{
Resource: pb.Resource{
Attributes: []*pb.KeyValue{
{Key: "logger", Value: &pb.AnyValue{StringValue: ptrTo("context")}},
{Key: "instance_id", Value: &pb.AnyValue{IntValue: ptrTo[int64](10)}},
{Key: "node_taints", Value: &pb.AnyValue{KeyValueList: &pb.KeyValueList{
Values: []*pb.KeyValue{
{Key: "role", Value: &pb.AnyValue{StringValue: ptrTo("dev")}},
{Key: "cluster_load_percent", Value: &pb.AnyValue{DoubleValue: ptrTo(0.55)}},
},
}}},
},
},
ScopeLogs: []pb.ScopeLogs{
{
LogRecords: []pb.LogRecord{
{TimeUnixNano: 1234, SeverityNumber: 1, Body: pb.AnyValue{StringValue: ptrTo("log-line-message")}},
{TimeUnixNano: 1235, SeverityNumber: 5, Body: pb.AnyValue{StringValue: ptrTo("log-line-message-msg-2")}},
},
},
},
},
{
ScopeLogs: []pb.ScopeLogs{
{
LogRecords: []pb.LogRecord{
{TimeUnixNano: 2345, SeverityNumber: 10, Body: pb.AnyValue{StringValue: ptrTo("log-line-resource-scope-1-0-0")}},
{TimeUnixNano: 2346, SeverityNumber: 10, Body: pb.AnyValue{StringValue: ptrTo("log-line-resource-scope-1-0-1")}},
},
},
{
LogRecords: []pb.LogRecord{
{TimeUnixNano: 2347, SeverityNumber: 12, Body: pb.AnyValue{StringValue: ptrTo("log-line-resource-scope-1-1-0")}},
{TraceID: "1234", SpanID: "45", ObservedTimeUnixNano: 2348, SeverityNumber: 12, Body: pb.AnyValue{StringValue: ptrTo("log-line-resource-scope-1-1-1")}},
{TraceID: "4bf92f3577b34da6a3ce929d0e0e4736", SpanID: "00f067aa0ba902b7", ObservedTimeUnixNano: 3333, Body: pb.AnyValue{StringValue: ptrTo("log-line-resource-scope-1-1-2")}},
},
},
},
},
},
[]int64{1234, 1235, 2345, 2346, 2347, 2348, 3333},
`{"logger":"context","instance_id":"10","node_taints":"{\"role\":\"dev\",\"cluster_load_percent\":0.55}","_msg":"log-line-message","severity":"Trace"}
{"logger":"context","instance_id":"10","node_taints":"{\"role\":\"dev\",\"cluster_load_percent\":0.55}","_msg":"log-line-message-msg-2","severity":"Debug"}
{"_msg":"log-line-resource-scope-1-0-0","severity":"Info2"}
{"_msg":"log-line-resource-scope-1-0-1","severity":"Info2"}
{"_msg":"log-line-resource-scope-1-1-0","severity":"Info4"}
{"_msg":"log-line-resource-scope-1-1-1","trace_id":"1234","span_id":"45","severity":"Info4"}
{"_msg":"log-line-resource-scope-1-1-2","trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","severity":"Unspecified"}`,
)
}
func ptrTo[T any](s T) *T {
return &s
}

View File

@@ -1,78 +0,0 @@
package opentelemetry
import (
"fmt"
"testing"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/opentelemetry/pb"
)
func BenchmarkParseProtobufRequest(b *testing.B) {
for _, scopes := range []int{1, 2} {
for _, rows := range []int{100, 1000} {
for _, attributes := range []int{5, 10} {
b.Run(fmt.Sprintf("scopes_%d/rows_%d/attributes_%d", scopes, rows, attributes), func(b *testing.B) {
benchmarkParseProtobufRequest(b, scopes, rows, attributes)
})
}
}
}
}
func benchmarkParseProtobufRequest(b *testing.B, streams, rows, labels int) {
blp := &insertutil.BenchmarkLogMessageProcessor{}
b.ReportAllocs()
b.SetBytes(int64(streams * rows))
b.RunParallel(func(pb *testing.PB) {
body := getProtobufBody(streams, rows, labels)
for pb.Next() {
if err := pushProtobufRequest(body, blp, false); err != nil {
panic(fmt.Errorf("unexpected error: %w", err))
}
}
})
}
func getProtobufBody(scopesCount, rowsCount, attributesCount int) []byte {
msg := "12345678910"
attrValues := []*pb.AnyValue{
{StringValue: ptrTo("string-attribute")},
{IntValue: ptrTo[int64](12345)},
{DoubleValue: ptrTo(3.14)},
}
attrs := make([]*pb.KeyValue, attributesCount)
for j := 0; j < attributesCount; j++ {
attrs[j] = &pb.KeyValue{
Key: fmt.Sprintf("key-%d", j),
Value: attrValues[j%3],
}
}
entries := make([]pb.LogRecord, rowsCount)
for j := 0; j < rowsCount; j++ {
entries[j] = pb.LogRecord{
TimeUnixNano: 12345678910, ObservedTimeUnixNano: 12345678910, Body: pb.AnyValue{StringValue: &msg},
}
}
scopes := make([]pb.ScopeLogs, scopesCount)
for j := 0; j < scopesCount; j++ {
scopes[j] = pb.ScopeLogs{
LogRecords: entries,
}
}
pr := pb.ExportLogsServiceRequest{
ResourceLogs: []pb.ResourceLogs{
{
Resource: pb.Resource{
Attributes: attrs,
},
ScopeLogs: scopes,
},
},
}
return pr.MarshalProtobuf(nil)
}

View File

@@ -1,590 +0,0 @@
package syslog
import (
"bufio"
"crypto/tls"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"net"
"sort"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/cgroup"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/ingestserver"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/netutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/protoparserutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/slicesutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/writeconcurrencylimiter"
"github.com/VictoriaMetrics/metrics"
)
var (
syslogTimezone = flag.String("syslog.timezone", "Local", "Timezone to use when parsing timestamps in RFC3164 syslog messages. Timezone must be a valid IANA Time Zone. "+
"For example: America/New_York, Europe/Berlin, Etc/GMT+3 . See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/")
streamFieldsTCP = flagutil.NewArrayString("syslog.streamFields.tcp", "Fields to use as log stream labels for logs ingested via the corresponding -syslog.listenAddr.tcp. "+
`See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#stream-fields`)
streamFieldsUDP = flagutil.NewArrayString("syslog.streamFields.udp", "Fields to use as log stream labels for logs ingested via the corresponding -syslog.listenAddr.udp. "+
`See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#stream-fields`)
ignoreFieldsTCP = flagutil.NewArrayString("syslog.ignoreFields.tcp", "Fields to ignore at logs ingested via the corresponding -syslog.listenAddr.tcp. "+
`See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#dropping-fields`)
ignoreFieldsUDP = flagutil.NewArrayString("syslog.ignoreFields.udp", "Fields to ignore at logs ingested via the corresponding -syslog.listenAddr.udp. "+
`See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#dropping-fields`)
extraFieldsTCP = flagutil.NewArrayString("syslog.extraFields.tcp", "Fields to add to logs ingested via the corresponding -syslog.listenAddr.tcp. "+
`See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#adding-extra-fields`)
extraFieldsUDP = flagutil.NewArrayString("syslog.extraFields.udp", "Fields to add to logs ingested via the corresponding -syslog.listenAddr.udp. "+
`See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#adding-extra-fields`)
tenantIDTCP = flagutil.NewArrayString("syslog.tenantID.tcp", "TenantID for logs ingested via the corresponding -syslog.listenAddr.tcp. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#multitenancy")
tenantIDUDP = flagutil.NewArrayString("syslog.tenantID.udp", "TenantID for logs ingested via the corresponding -syslog.listenAddr.udp. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#multitenancy")
listenAddrTCP = flagutil.NewArrayString("syslog.listenAddr.tcp", "Comma-separated list of TCP addresses to listen to for Syslog messages. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/")
listenAddrUDP = flagutil.NewArrayString("syslog.listenAddr.udp", "Comma-separated list of UDP address to listen to for Syslog messages. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/")
tlsEnable = flagutil.NewArrayBool("syslog.tls", "Whether to enable TLS for receiving syslog messages at the corresponding -syslog.listenAddr.tcp. "+
"The corresponding -syslog.tlsCertFile and -syslog.tlsKeyFile must be set if -syslog.tls is set. See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#security")
tlsCertFile = flagutil.NewArrayString("syslog.tlsCertFile", "Path to file with TLS certificate for the corresponding -syslog.listenAddr.tcp if the corresponding -syslog.tls is set. "+
"Prefer ECDSA certs instead of RSA certs as RSA certs are slower. The provided certificate file is automatically re-read every second, so it can be dynamically updated. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#security")
tlsKeyFile = flagutil.NewArrayString("syslog.tlsKeyFile", "Path to file with TLS key for the corresponding -syslog.listenAddr.tcp if the corresponding -syslog.tls is set. "+
"The provided key file is automatically re-read every second, so it can be dynamically updated. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#security")
tlsCipherSuites = flagutil.NewArrayString("syslog.tlsCipherSuites", "Optional list of TLS cipher suites for -syslog.listenAddr.tcp if -syslog.tls is set. "+
"See the list of supported cipher suites at https://pkg.go.dev/crypto/tls#pkg-constants . "+
"See also https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#security")
tlsMinVersion = flag.String("syslog.tlsMinVersion", "TLS13", "The minimum TLS version to use for -syslog.listenAddr.tcp if -syslog.tls is set. "+
"Supported values: TLS10, TLS11, TLS12, TLS13. "+
"See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#security")
compressMethodTCP = flagutil.NewArrayString("syslog.compressMethod.tcp", "Compression method for syslog messages received at the corresponding -syslog.listenAddr.tcp. "+
"Supported values: none, gzip, deflate. See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#compression")
compressMethodUDP = flagutil.NewArrayString("syslog.compressMethod.udp", "Compression method for syslog messages received at the corresponding -syslog.listenAddr.udp. "+
"Supported values: none, gzip, deflate. See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#compression")
useLocalTimestampTCP = flagutil.NewArrayBool("syslog.useLocalTimestamp.tcp", "Whether to use local timestamp instead of the original timestamp for the ingested syslog messages "+
"at the corresponding -syslog.listenAddr.tcp. See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#log-timestamps")
useLocalTimestampUDP = flagutil.NewArrayBool("syslog.useLocalTimestamp.udp", "Whether to use local timestamp instead of the original timestamp for the ingested syslog messages "+
"at the corresponding -syslog.listenAddr.udp. See https://docs.victoriametrics.com/victorialogs/data-ingestion/syslog/#log-timestamps")
)
// MustInit initializes syslog parser at the given -syslog.listenAddr.tcp and -syslog.listenAddr.udp ports
//
// This function must be called after flag.Parse().
//
// MustStop() must be called in order to free up resources occupied by the initialized syslog parser.
func MustInit() {
if workersStopCh != nil {
logger.Panicf("BUG: MustInit() called twice without MustStop() call")
}
workersStopCh = make(chan struct{})
for argIdx, addr := range *listenAddrTCP {
workersWG.Add(1)
go func(addr string, argIdx int) {
runTCPListener(addr, argIdx)
workersWG.Done()
}(addr, argIdx)
}
for argIdx, addr := range *listenAddrUDP {
workersWG.Add(1)
go func(addr string, argIdx int) {
runUDPListener(addr, argIdx)
workersWG.Done()
}(addr, argIdx)
}
currentYear := time.Now().Year()
globalCurrentYear.Store(int64(currentYear))
workersWG.Add(1)
go func() {
ticker := time.NewTicker(time.Minute)
for {
select {
case <-workersStopCh:
ticker.Stop()
workersWG.Done()
return
case <-ticker.C:
currentYear := time.Now().Year()
globalCurrentYear.Store(int64(currentYear))
}
}
}()
if *syslogTimezone != "" {
tz, err := time.LoadLocation(*syslogTimezone)
if err != nil {
logger.Fatalf("cannot parse -syslog.timezone=%q: %s", *syslogTimezone, err)
}
globalTimezone = tz
} else {
globalTimezone = time.Local
}
}
var (
globalCurrentYear atomic.Int64
globalTimezone *time.Location
)
var (
workersWG sync.WaitGroup
workersStopCh chan struct{}
)
// MustStop stops syslog parser initialized via MustInit()
func MustStop() {
close(workersStopCh)
workersWG.Wait()
workersStopCh = nil
}
func runUDPListener(addr string, argIdx int) {
ln, err := net.ListenPacket(netutil.GetUDPNetwork(), addr)
if err != nil {
logger.Fatalf("cannot start UDP syslog server at %q: %s", addr, err)
}
tenantIDStr := tenantIDUDP.GetOptionalArg(argIdx)
tenantID, err := logstorage.ParseTenantID(tenantIDStr)
if err != nil {
logger.Fatalf("cannot parse -syslog.tenantID.udp=%q for -syslog.listenAddr.udp=%q: %s", tenantIDStr, addr, err)
}
compressMethod := compressMethodUDP.GetOptionalArg(argIdx)
checkCompressMethod(compressMethod, addr, "udp")
useLocalTimestamp := useLocalTimestampUDP.GetOptionalArg(argIdx)
streamFieldsStr := streamFieldsUDP.GetOptionalArg(argIdx)
streamFields, err := parseFieldsList(streamFieldsStr)
if err != nil {
logger.Fatalf("cannot parse -syslog.streamFields.udp=%q for -syslog.listenAddr.udp=%q: %s", streamFieldsStr, addr, err)
}
ignoreFieldsStr := ignoreFieldsUDP.GetOptionalArg(argIdx)
ignoreFields, err := parseFieldsList(ignoreFieldsStr)
if err != nil {
logger.Fatalf("cannot parse -syslog.ignoreFields.udp=%q for -syslog.listenAddr.udp=%q: %s", ignoreFieldsStr, addr, err)
}
extraFieldsStr := extraFieldsUDP.GetOptionalArg(argIdx)
extraFields, err := parseExtraFields(extraFieldsStr)
if err != nil {
logger.Fatalf("cannot parse -syslog.extraFields.udp=%q for -syslog.listenAddr.udp=%q: %s", extraFieldsStr, addr, err)
}
doneCh := make(chan struct{})
go func() {
serveUDP(ln, tenantID, compressMethod, useLocalTimestamp, streamFields, ignoreFields, extraFields)
close(doneCh)
}()
logger.Infof("started accepting syslog messages at -syslog.listenAddr.udp=%q", addr)
<-workersStopCh
if err := ln.Close(); err != nil {
logger.Fatalf("syslog: cannot close UDP listener at %s: %s", addr, err)
}
<-doneCh
logger.Infof("finished accepting syslog messages at -syslog.listenAddr.udp=%q", addr)
}
func runTCPListener(addr string, argIdx int) {
var tlsConfig *tls.Config
if tlsEnable.GetOptionalArg(argIdx) {
certFile := tlsCertFile.GetOptionalArg(argIdx)
keyFile := tlsKeyFile.GetOptionalArg(argIdx)
tc, err := netutil.GetServerTLSConfig(certFile, keyFile, *tlsMinVersion, *tlsCipherSuites)
if err != nil {
logger.Fatalf("cannot load TLS cert from -syslog.tlsCertFile=%q, -syslog.tlsKeyFile=%q, -syslog.tlsMinVersion=%q, -syslog.tlsCipherSuites=%q: %s",
certFile, keyFile, *tlsMinVersion, *tlsCipherSuites, err)
}
tlsConfig = tc
}
ln, err := netutil.NewTCPListener("syslog", addr, false, tlsConfig)
if err != nil {
logger.Fatalf("syslog: cannot start TCP listener at %s: %s", addr, err)
}
tenantIDStr := tenantIDTCP.GetOptionalArg(argIdx)
tenantID, err := logstorage.ParseTenantID(tenantIDStr)
if err != nil {
logger.Fatalf("cannot parse -syslog.tenantID.tcp=%q for -syslog.listenAddr.tcp=%q: %s", tenantIDStr, addr, err)
}
compressMethod := compressMethodTCP.GetOptionalArg(argIdx)
checkCompressMethod(compressMethod, addr, "tcp")
useLocalTimestamp := useLocalTimestampTCP.GetOptionalArg(argIdx)
streamFieldsStr := streamFieldsTCP.GetOptionalArg(argIdx)
streamFields, err := parseFieldsList(streamFieldsStr)
if err != nil {
logger.Fatalf("cannot parse -syslog.streamFields.tcp=%q for -syslog.listenAddr.tcp=%q: %s", streamFieldsStr, addr, err)
}
ignoreFieldsStr := ignoreFieldsTCP.GetOptionalArg(argIdx)
ignoreFields, err := parseFieldsList(ignoreFieldsStr)
if err != nil {
logger.Fatalf("cannot parse -syslog.ignoreFields.tcp=%q for -syslog.listenAddr.tcp=%q: %s", ignoreFieldsStr, addr, err)
}
extraFieldsStr := extraFieldsTCP.GetOptionalArg(argIdx)
extraFields, err := parseExtraFields(extraFieldsStr)
if err != nil {
logger.Fatalf("cannot parse -syslog.extraFields.tcp=%q for -syslog.listenAddr.tcp=%q: %s", extraFieldsStr, addr, err)
}
doneCh := make(chan struct{})
go func() {
serveTCP(ln, tenantID, compressMethod, useLocalTimestamp, streamFields, ignoreFields, extraFields)
close(doneCh)
}()
logger.Infof("started accepting syslog messages at -syslog.listenAddr.tcp=%q", addr)
<-workersStopCh
if err := ln.Close(); err != nil {
logger.Fatalf("syslog: cannot close TCP listener at %s: %s", addr, err)
}
<-doneCh
logger.Infof("finished accepting syslog messages at -syslog.listenAddr.tcp=%q", addr)
}
func checkCompressMethod(compressMethod, addr, protocol string) {
switch compressMethod {
case "", "none", "zstd", "gzip", "deflate":
return
default:
logger.Fatalf("unsupported -syslog.compressMethod.%s=%q for -syslog.listenAddr.%s=%q; supported values: 'none', 'zstd', 'gzip', 'deflate'", protocol, compressMethod, protocol, addr)
}
}
func serveUDP(ln net.PacketConn, tenantID logstorage.TenantID, encoding string, useLocalTimestamp bool, streamFields, ignoreFields []string, extraFields []logstorage.Field) {
gomaxprocs := cgroup.AvailableCPUs()
var wg sync.WaitGroup
localAddr := ln.LocalAddr()
for i := 0; i < gomaxprocs; i++ {
wg.Add(1)
go func() {
defer wg.Done()
cp := insertutil.GetCommonParamsForSyslog(tenantID, streamFields, ignoreFields, extraFields)
var bb bytesutil.ByteBuffer
bb.B = bytesutil.ResizeNoCopyNoOverallocate(bb.B, 64*1024)
for {
bb.Reset()
bb.B = bb.B[:cap(bb.B)]
n, remoteAddr, err := ln.ReadFrom(bb.B)
if err != nil {
udpErrorsTotal.Inc()
var ne net.Error
if errors.As(err, &ne) {
if ne.Temporary() {
logger.Errorf("syslog: temporary error when listening for UDP at %q: %s", localAddr, err)
time.Sleep(time.Second)
continue
}
if strings.Contains(err.Error(), "use of closed network connection") {
break
}
}
logger.Errorf("syslog: cannot read UDP data from %s at %s: %s", remoteAddr, localAddr, err)
continue
}
bb.B = bb.B[:n]
udpRequestsTotal.Inc()
if err := processStream("udp", bb.NewReader(), encoding, useLocalTimestamp, cp); err != nil {
logger.Errorf("syslog: cannot process UDP data from %s at %s: %s", remoteAddr, localAddr, err)
}
}
}()
}
wg.Wait()
}
func serveTCP(ln net.Listener, tenantID logstorage.TenantID, encoding string, useLocalTimestamp bool, streamFields, ignoreFields []string, extraFields []logstorage.Field) {
var cm ingestserver.ConnsMap
cm.Init("syslog")
var wg sync.WaitGroup
addr := ln.Addr()
for {
c, err := ln.Accept()
if err != nil {
var ne net.Error
if errors.As(err, &ne) {
if ne.Temporary() {
logger.Errorf("syslog: temporary error when listening for TCP addr %q: %s", addr, err)
time.Sleep(time.Second)
continue
}
if strings.Contains(err.Error(), "use of closed network connection") {
break
}
logger.Fatalf("syslog: unrecoverable error when accepting TCP connections at %q: %s", addr, err)
}
logger.Fatalf("syslog: unexpected error when accepting TCP connections at %q: %s", addr, err)
}
if !cm.Add(c) {
_ = c.Close()
break
}
wg.Add(1)
go func() {
cp := insertutil.GetCommonParamsForSyslog(tenantID, streamFields, ignoreFields, extraFields)
if err := processStream("tcp", c, encoding, useLocalTimestamp, cp); err != nil {
logger.Errorf("syslog: cannot process TCP data at %q: %s", addr, err)
}
cm.Delete(c)
_ = c.Close()
wg.Done()
}()
}
cm.CloseAll(0)
wg.Wait()
}
// processStream parses a stream of syslog messages from r and ingests them into vlstorage.
func processStream(protocol string, r io.Reader, encoding string, useLocalTimestamp bool, cp *insertutil.CommonParams) error {
if err := vlstorage.CanWriteData(); err != nil {
return err
}
lmp := cp.NewLogMessageProcessor("syslog_"+protocol, true)
err := processStreamInternal(r, encoding, useLocalTimestamp, lmp)
lmp.MustClose()
return err
}
func processStreamInternal(r io.Reader, encoding string, useLocalTimestamp bool, lmp insertutil.LogMessageProcessor) error {
reader, err := protoparserutil.GetUncompressedReader(r, encoding)
if err != nil {
return fmt.Errorf("cannot decode syslog data: %w", err)
}
defer protoparserutil.PutUncompressedReader(reader)
return processUncompressedStream(reader, useLocalTimestamp, lmp)
}
func processUncompressedStream(r io.Reader, useLocalTimestamp bool, lmp insertutil.LogMessageProcessor) error {
wcr := writeconcurrencylimiter.GetReader(r)
defer writeconcurrencylimiter.PutReader(wcr)
slr := getSyslogLineReader(wcr)
defer putSyslogLineReader(slr)
n := 0
for {
ok := slr.nextLine()
wcr.DecConcurrency()
if !ok {
break
}
currentYear := int(globalCurrentYear.Load())
err := processLine(slr.line, currentYear, globalTimezone, useLocalTimestamp, lmp)
if err != nil {
errorsTotal.Inc()
return fmt.Errorf("cannot read line #%d: %s", n, err)
}
n++
}
return slr.Error()
}
type syslogLineReader struct {
line []byte
br *bufio.Reader
err error
}
func (slr *syslogLineReader) reset(r io.Reader) {
slr.line = slr.line[:0]
slr.br.Reset(r)
slr.err = nil
}
// Error returns the last error occurred in slr.
func (slr *syslogLineReader) Error() error {
if slr.err == nil || slr.err == io.EOF {
return nil
}
return slr.err
}
// nextLine reads the next syslog line from slr and stores it at slr.line.
//
// false is returned if the next line cannot be read. Error() must be called in this case
// in order to verify whether there is an error or just slr stream has been finished.
func (slr *syslogLineReader) nextLine() bool {
if slr.err != nil {
return false
}
again:
prefix, err := slr.br.ReadSlice(' ')
if err != nil {
if err != io.EOF {
slr.err = fmt.Errorf("cannot read message frame prefix: %w", err)
return false
}
if len(prefix) == 0 {
slr.err = err
return false
}
}
// skip empty lines
for len(prefix) > 0 && prefix[0] == '\n' {
prefix = prefix[1:]
}
if len(prefix) == 0 {
// An empty prefix or a prefix with empty lines - try reading yet another prefix.
goto again
}
if prefix[0] >= '0' && prefix[0] <= '9' {
// This is octet-counting method. See https://www.ietf.org/archive/id/draft-gerhards-syslog-plain-tcp-07.html#msgxfer
msgLenStr := bytesutil.ToUnsafeString(prefix[:len(prefix)-1])
msgLen, err := strconv.ParseUint(msgLenStr, 10, 64)
if err != nil {
slr.err = fmt.Errorf("cannot parse message length from %q: %w", msgLenStr, err)
return false
}
if maxMsgLen := insertutil.MaxLineSizeBytes.IntN(); msgLen > uint64(maxMsgLen) {
slr.err = fmt.Errorf("cannot read message longer than %d bytes; msgLen=%d", maxMsgLen, msgLen)
return false
}
slr.line = slicesutil.SetLength(slr.line, int(msgLen))
if _, err := io.ReadFull(slr.br, slr.line); err != nil {
slr.err = fmt.Errorf("cannot read message with size %d bytes: %w", msgLen, err)
return false
}
return true
}
// This is octet-stuffing method. See https://www.ietf.org/archive/id/draft-gerhards-syslog-plain-tcp-07.html#octet-stuffing-legacy
slr.line = append(slr.line[:0], prefix...)
for {
line, err := slr.br.ReadSlice('\n')
if err == nil {
slr.line = append(slr.line, line[:len(line)-1]...)
return true
}
if err == io.EOF {
slr.line = append(slr.line, line...)
return true
}
if err == bufio.ErrBufferFull {
slr.line = append(slr.line, line...)
continue
}
slr.err = fmt.Errorf("cannot read message in octet-stuffing method: %w", err)
return false
}
}
func getSyslogLineReader(r io.Reader) *syslogLineReader {
v := syslogLineReaderPool.Get()
if v == nil {
br := bufio.NewReaderSize(r, 64*1024)
return &syslogLineReader{
br: br,
}
}
slr := v.(*syslogLineReader)
slr.reset(r)
return slr
}
func putSyslogLineReader(slr *syslogLineReader) {
syslogLineReaderPool.Put(slr)
}
var syslogLineReaderPool sync.Pool
func processLine(line []byte, currentYear int, timezone *time.Location, useLocalTimestamp bool, lmp insertutil.LogMessageProcessor) error {
p := logstorage.GetSyslogParser(currentYear, timezone)
lineStr := bytesutil.ToUnsafeString(line)
p.Parse(lineStr)
var ts int64
if useLocalTimestamp {
ts = time.Now().UnixNano()
} else {
nsecs, err := insertutil.ExtractTimestampFromFields("timestamp", p.Fields)
if err != nil {
return fmt.Errorf("cannot get timestamp from syslog line %q: %w", line, err)
}
ts = nsecs
}
logstorage.RenameField(p.Fields, msgFields, "_msg")
lmp.AddRow(ts, p.Fields, nil)
logstorage.PutSyslogParser(p)
return nil
}
var msgFields = []string{"message"}
var (
errorsTotal = metrics.NewCounter(`vl_errors_total{type="syslog"}`)
udpRequestsTotal = metrics.NewCounter(`vl_udp_reqests_total{type="syslog"}`)
udpErrorsTotal = metrics.NewCounter(`vl_udp_errors_total{type="syslog"}`)
)
func parseFieldsList(s string) ([]string, error) {
if s == "" {
return nil, nil
}
var a []string
err := json.Unmarshal([]byte(s), &a)
return a, err
}
func parseExtraFields(s string) ([]logstorage.Field, error) {
if s == "" {
return nil, nil
}
var m map[string]string
if err := json.Unmarshal([]byte(s), &m); err != nil {
return nil, err
}
fields := make([]logstorage.Field, 0, len(m))
for k, v := range m {
fields = append(fields, logstorage.Field{
Name: k,
Value: v,
})
}
sort.Slice(fields, func(i, j int) bool {
return fields[i].Name < fields[j].Name
})
return fields, nil
}

View File

@@ -1,129 +0,0 @@
package syslog
import (
"bytes"
"reflect"
"testing"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutil"
)
func TestSyslogLineReader_Success(t *testing.T) {
f := func(data string, linesExpected []string) {
t.Helper()
r := bytes.NewBufferString(data)
slr := getSyslogLineReader(r)
defer putSyslogLineReader(slr)
var lines []string
for slr.nextLine() {
lines = append(lines, string(slr.line))
}
if err := slr.Error(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !reflect.DeepEqual(lines, linesExpected) {
t.Fatalf("unexpected lines read;\ngot\n%q\nwant\n%q", lines, linesExpected)
}
}
f("", nil)
f("\n", nil)
f("\n\n\n", nil)
f("foobar", []string{"foobar"})
f("foobar\n", []string{"foobar\n"})
f("\n\nfoo\n\nbar\n\n", []string{"foo\n\nbar\n\n"})
f(`Jun 3 12:08:33 abcd systemd: Starting Update the local ESM caches...`, []string{"Jun 3 12:08:33 abcd systemd: Starting Update the local ESM caches..."})
f(`Jun 3 12:08:33 abcd systemd: Starting Update the local ESM caches...
48 <165>Jun 4 12:08:33 abcd systemd[345]: abc defg<123>1 2023-06-03T17:42:12.345Z mymachine.example.com appname 12345 ID47 [exampleSDID@32473 iut="3" eventSource="Application 123 = ] 56" eventID="11211"] This is a test message with structured data.
`, []string{
"Jun 3 12:08:33 abcd systemd: Starting Update the local ESM caches...",
"<165>Jun 4 12:08:33 abcd systemd[345]: abc defg",
`<123>1 2023-06-03T17:42:12.345Z mymachine.example.com appname 12345 ID47 [exampleSDID@32473 iut="3" eventSource="Application 123 = ] 56" eventID="11211"] This is a test message with structured data.`,
})
}
func TestSyslogLineReader_Failure(t *testing.T) {
f := func(data string) {
t.Helper()
r := bytes.NewBufferString(data)
slr := getSyslogLineReader(r)
defer putSyslogLineReader(slr)
if slr.nextLine() {
t.Fatalf("expecting failure to read the first line")
}
if err := slr.Error(); err == nil {
t.Fatalf("expecting non-nil error")
}
}
// invalid format for message size
f("12foo bar")
// too big message size
f("123 aa")
f("1233423432 abc")
}
func TestProcessStreamInternal_Success(t *testing.T) {
f := func(data string, currentYear int, timestampsExpected []int64, resultExpected string) {
t.Helper()
MustInit()
defer MustStop()
globalTimezone = time.UTC
globalCurrentYear.Store(int64(currentYear))
tlp := &insertutil.TestLogMessageProcessor{}
r := bytes.NewBufferString(data)
if err := processStreamInternal(r, "", false, tlp); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if err := tlp.Verify(timestampsExpected, resultExpected); err != nil {
t.Fatal(err)
}
}
data := `Jun 3 12:08:33 abcd systemd: Starting Update the local ESM caches...
48 <165>Jun 4 12:08:33 abcd systemd[345]: abc defg<123>1 2023-06-03T17:42:12.345Z mymachine.example.com appname 12345 ID47 [exampleSDID@32473 iut="3" eventSource="Application 123 = ] 56" eventID="11211"] This is a test message with structured data.
`
currentYear := 2023
timestampsExpected := []int64{1685794113000000000, 1685880513000000000, 1685814132345000000}
resultExpected := `{"format":"rfc3164","hostname":"abcd","app_name":"systemd","_msg":"Starting Update the local ESM caches..."}
{"priority":"165","facility":"20","severity":"5","format":"rfc3164","hostname":"abcd","app_name":"systemd","proc_id":"345","_msg":"abc defg"}
{"priority":"123","facility":"15","severity":"3","format":"rfc5424","hostname":"mymachine.example.com","app_name":"appname","proc_id":"12345","msg_id":"ID47","exampleSDID@32473.iut":"3","exampleSDID@32473.eventSource":"Application 123 = ] 56","exampleSDID@32473.eventID":"11211","_msg":"This is a test message with structured data."}`
f(data, currentYear, timestampsExpected, resultExpected)
}
func TestProcessStreamInternal_Failure(t *testing.T) {
f := func(data string) {
t.Helper()
MustInit()
defer MustStop()
tlp := &insertutil.TestLogMessageProcessor{}
r := bytes.NewBufferString(data)
if err := processStreamInternal(r, "", false, tlp); err == nil {
t.Fatalf("expecting non-nil error")
}
}
// invalid format for message size
f("12foo bar")
// too big message size
f("123 foo")
f("123456789 bar")
}

View File

@@ -1,109 +0,0 @@
# All these commands must run from repository root.
vlogscli:
APP_NAME=vlogscli $(MAKE) app-local
vlogscli-race:
APP_NAME=vlogscli RACE=-race $(MAKE) app-local
vlogscli-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker
vlogscli-pure-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker-pure
vlogscli-linux-amd64-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker-linux-amd64
vlogscli-linux-arm-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker-linux-arm
vlogscli-linux-arm64-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker-linux-arm64
vlogscli-linux-ppc64le-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker-linux-ppc64le
vlogscli-linux-386-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker-linux-386
vlogscli-darwin-amd64-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker-darwin-amd64
vlogscli-darwin-arm64-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker-darwin-arm64
vlogscli-freebsd-amd64-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker-freebsd-amd64
vlogscli-openbsd-amd64-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker-openbsd-amd64
vlogscli-windows-amd64-prod:
APP_NAME=vlogscli $(MAKE) app-via-docker-windows-amd64
package-vlogscli:
APP_NAME=vlogscli $(MAKE) package-via-docker
package-vlogscli-pure:
APP_NAME=vlogscli $(MAKE) package-via-docker-pure
package-vlogscli-amd64:
APP_NAME=vlogscli $(MAKE) package-via-docker-amd64
package-vlogscli-arm:
APP_NAME=vlogscli $(MAKE) package-via-docker-arm
package-vlogscli-arm64:
APP_NAME=vlogscli $(MAKE) package-via-docker-arm64
package-vlogscli-ppc64le:
APP_NAME=vlogscli $(MAKE) package-via-docker-ppc64le
package-vlogscli-386:
APP_NAME=vlogscli $(MAKE) package-via-docker-386
publish-vlogscli:
APP_NAME=vlogscli $(MAKE) publish-via-docker
vlogscli-linux-amd64:
APP_NAME=vlogscli CGO_ENABLED=1 GOOS=linux GOARCH=amd64 $(MAKE) app-local-goos-goarch
vlogscli-linux-arm:
APP_NAME=vlogscli CGO_ENABLED=0 GOOS=linux GOARCH=arm $(MAKE) app-local-goos-goarch
vlogscli-linux-arm64:
APP_NAME=vlogscli CGO_ENABLED=0 GOOS=linux GOARCH=arm64 $(MAKE) app-local-goos-goarch
vlogscli-linux-ppc64le:
APP_NAME=vlogscli CGO_ENABLED=0 GOOS=linux GOARCH=ppc64le $(MAKE) app-local-goos-goarch
vlogscli-linux-s390x:
APP_NAME=vlogscli CGO_ENABLED=0 GOOS=linux GOARCH=s390x $(MAKE) app-local-goos-goarch
vlogscli-linux-loong64:
APP_NAME=vlogscli CGO_ENABLED=0 GOOS=linux GOARCH=loong64 $(MAKE) app-local-goos-goarch
vlogscli-linux-386:
APP_NAME=vlogscli CGO_ENABLED=0 GOOS=linux GOARCH=386 $(MAKE) app-local-goos-goarch
vlogscli-darwin-amd64:
APP_NAME=vlogscli CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 $(MAKE) app-local-goos-goarch
vlogscli-darwin-arm64:
APP_NAME=vlogscli CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 $(MAKE) app-local-goos-goarch
vlogscli-freebsd-amd64:
APP_NAME=vlogscli CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 $(MAKE) app-local-goos-goarch
vlogscli-openbsd-amd64:
APP_NAME=vlogscli CGO_ENABLED=0 GOOS=openbsd GOARCH=amd64 $(MAKE) app-local-goos-goarch
vlogscli-windows-amd64:
GOARCH=amd64 APP_NAME=vlogscli $(MAKE) app-local-windows-goarch
vlogscli-pure:
APP_NAME=vlogscli $(MAKE) app-local-pure
run-vlogscli:
APP_NAME=vlogscli $(MAKE) run-via-docker

View File

@@ -1,5 +1 @@
# vlogscli
Command-line utility for querying [VictoriaLogs](https://docs.victoriametrics.com/victorialogs/).
See [these docs](https://docs.victoriametrics.com/victorialogs/querying/vlogscli/).
VictoriaLogs source code has been moved to [github.com/VictoriaMetrics/VictoriaLogs](https://github.com/VictoriaMetrics/VictoriaLogs/).

View File

@@ -1,6 +0,0 @@
ARG base_image=non-existing
FROM $base_image
ENTRYPOINT ["/vlogscli-prod"]
ARG src_binary=non-existing
COPY $src_binary ./vlogscli-prod

View File

@@ -1,245 +0,0 @@
package main
import (
"bufio"
"encoding/json"
"fmt"
"io"
"sort"
"strings"
"sync"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
)
type outputMode int
const (
outputModeJSONMultiline = outputMode(0)
outputModeJSONSingleline = outputMode(1)
outputModeLogfmt = outputMode(2)
outputModeCompact = outputMode(3)
)
func getOutputFormatter(outputMode outputMode) func(w io.Writer, fields []logstorage.Field) error {
switch outputMode {
case outputModeJSONMultiline:
return func(w io.Writer, fields []logstorage.Field) error {
return writeJSONObject(w, fields, true)
}
case outputModeJSONSingleline:
return func(w io.Writer, fields []logstorage.Field) error {
return writeJSONObject(w, fields, false)
}
case outputModeLogfmt:
return writeLogfmtObject
case outputModeCompact:
return writeCompactObject
default:
panic(fmt.Errorf("BUG: unexpected outputMode=%d", outputMode))
}
}
type jsonPrettifier struct {
r io.ReadCloser
formatter func(w io.Writer, fields []logstorage.Field) error
d *json.Decoder
pr *io.PipeReader
pw *io.PipeWriter
bw *bufio.Writer
wg sync.WaitGroup
}
func newJSONPrettifier(r io.ReadCloser, outputMode outputMode) *jsonPrettifier {
d := json.NewDecoder(r)
pr, pw := io.Pipe()
bw := bufio.NewWriter(pw)
formatter := getOutputFormatter(outputMode)
jp := &jsonPrettifier{
r: r,
formatter: formatter,
d: d,
pr: pr,
pw: pw,
bw: bw,
}
jp.wg.Add(1)
go func() {
defer jp.wg.Done()
err := jp.prettifyJSONLines()
jp.closePipesWithError(err)
}()
return jp
}
func (jp *jsonPrettifier) closePipesWithError(err error) {
_ = jp.pr.CloseWithError(err)
_ = jp.pw.CloseWithError(err)
}
func (jp *jsonPrettifier) prettifyJSONLines() error {
for jp.d.More() {
fields, err := readNextJSONObject(jp.d)
if err != nil {
return err
}
sort.Slice(fields, func(i, j int) bool {
return fields[i].Name < fields[j].Name
})
if err := jp.formatter(jp.bw, fields); err != nil {
return err
}
// Flush bw after every output line in order to show results as soon as they appear.
if err := jp.bw.Flush(); err != nil {
return err
}
}
return nil
}
func (jp *jsonPrettifier) Close() error {
jp.closePipesWithError(io.ErrUnexpectedEOF)
err := jp.r.Close()
jp.wg.Wait()
return err
}
func (jp *jsonPrettifier) Read(p []byte) (int, error) {
return jp.pr.Read(p)
}
func readNextJSONObject(d *json.Decoder) ([]logstorage.Field, error) {
t, err := d.Token()
if err != nil {
return nil, fmt.Errorf("cannot read '{': %w", err)
}
delim, ok := t.(json.Delim)
if !ok || delim.String() != "{" {
return nil, fmt.Errorf("unexpected token read; got %q; want '{'", delim)
}
var fields []logstorage.Field
for {
// Read object key
t, err := d.Token()
if err != nil {
return nil, fmt.Errorf("cannot read JSON object key or closing brace: %w", err)
}
delim, ok := t.(json.Delim)
if ok {
if delim.String() == "}" {
return fields, nil
}
return nil, fmt.Errorf("unexpected delimiter read; got %q; want '}'", delim)
}
key, ok := t.(string)
if !ok {
return nil, fmt.Errorf("unexpected token read for object key: %v; want string or '}'", t)
}
// read object value
t, err = d.Token()
if err != nil {
return nil, fmt.Errorf("cannot read JSON object value: %w", err)
}
value, ok := t.(string)
if !ok {
return nil, fmt.Errorf("unexpected token read for object value: %v; want string", t)
}
fields = append(fields, logstorage.Field{
Name: key,
Value: value,
})
}
}
func writeLogfmtObject(w io.Writer, fields []logstorage.Field) error {
data := logstorage.MarshalFieldsToLogfmt(nil, fields)
_, err := fmt.Fprintf(w, "%s\n", data)
return err
}
func writeCompactObject(w io.Writer, fields []logstorage.Field) error {
if len(fields) == 1 {
// Just write field value as is without name
_, err := fmt.Fprintf(w, "%s\n", fields[0].Value)
return err
}
if len(fields) == 2 && (fields[0].Name == "_time" || fields[1].Name == "_time") {
// Write _time\tfieldValue as is
if fields[0].Name == "_time" {
_, err := fmt.Fprintf(w, "%s\t%s\n", fields[0].Value, fields[1].Value)
return err
}
_, err := fmt.Fprintf(w, "%s\t%s\n", fields[1].Value, fields[0].Value)
return err
}
// Fall back to logfmt
return writeLogfmtObject(w, fields)
}
func writeJSONObject(w io.Writer, fields []logstorage.Field, isMultiline bool) error {
if len(fields) == 0 {
fmt.Fprintf(w, "{}\n")
return nil
}
fmt.Fprintf(w, "{")
writeNewlineIfNeeded(w, isMultiline)
if err := writeJSONObjectKeyValue(w, fields[0], isMultiline); err != nil {
return err
}
for _, f := range fields[1:] {
fmt.Fprintf(w, ",")
writeNewlineIfNeeded(w, isMultiline)
if err := writeJSONObjectKeyValue(w, f, isMultiline); err != nil {
return err
}
}
writeNewlineIfNeeded(w, isMultiline)
fmt.Fprintf(w, "}\n")
return nil
}
func writeNewlineIfNeeded(w io.Writer, isMultiline bool) {
if isMultiline {
fmt.Fprintf(w, "\n")
}
}
func writeJSONObjectKeyValue(w io.Writer, f logstorage.Field, isMultiline bool) error {
key := getJSONString(f.Name)
value := getJSONString(f.Value)
if isMultiline {
_, err := fmt.Fprintf(w, " %s: %s", key, value)
return err
}
_, err := fmt.Fprintf(w, "%s:%s", key, value)
return err
}
func getJSONString(s string) string {
data, err := json.Marshal(s)
if err != nil {
panic(fmt.Errorf("unexpected error when marshaling string to JSON: %w", err))
}
return jsonHTMLReplacer.Replace(string(data))
}
var jsonHTMLReplacer = strings.NewReplacer(
`\u003c`, "\u003c",
`\u003e`, "\u003e",
`\u0026`, "\u0026",
)

View File

@@ -1,120 +0,0 @@
package main
import (
"errors"
"fmt"
"io"
"os"
"os/exec"
"os/signal"
"sync"
"syscall"
"github.com/mattn/go-isatty"
)
func isTerminal() bool {
return isatty.IsTerminal(os.Stdout.Fd()) && isatty.IsTerminal(os.Stderr.Fd())
}
func readWithLess(r io.Reader, wrapLongLines bool) error {
if !isTerminal() {
// Just write everything to stdout if no terminal is available.
_, err := io.Copy(os.Stdout, r)
if err != nil && !isErrPipe(err) {
return fmt.Errorf("error when forwarding data to stdout: %w", err)
}
if err := os.Stdout.Sync(); err != nil {
return fmt.Errorf("cannot sync data to stdout: %w", err)
}
return nil
}
pr, pw, err := os.Pipe()
if err != nil {
return fmt.Errorf("cannot create pipe: %w", err)
}
defer func() {
_ = pr.Close()
_ = pw.Close()
}()
// Ignore Ctrl+C in the current process, so 'less' could handle it properly
cancel := ignoreSignals(os.Interrupt)
defer cancel()
// Start 'less' process
path, err := exec.LookPath("less")
if err != nil {
return fmt.Errorf("cannot find 'less' command: %w", err)
}
opts := []string{"less", "-F", "-X"}
if !wrapLongLines {
opts = append(opts, "-S")
}
p, err := os.StartProcess(path, opts, &os.ProcAttr{
Env: append(os.Environ(), "LESSCHARSET=utf-8"),
Files: []*os.File{pr, os.Stdout, os.Stderr},
})
if err != nil {
return fmt.Errorf("cannot start 'less' process: %w", err)
}
// Close pr after 'less' finishes in a parallel goroutine
// in order to unblock forwarding data to stopped 'less' below.
waitch := make(chan *os.ProcessState)
go func() {
// Wait for 'less' process to finish.
ps, err := p.Wait()
if err != nil {
fatalf("unexpected error when waiting for 'less' process: %w", err)
}
_ = pr.Close()
waitch <- ps
}()
// Forward data from r to 'less'
_, err = io.Copy(pw, r)
_ = pw.Sync()
_ = pw.Close()
// Wait until 'less' finished
ps := <-waitch
// Verify 'less' status.
if !ps.Success() {
return fmt.Errorf("'less' finished with unexpected code %d", ps.ExitCode())
}
if err != nil && !isErrPipe(err) {
return fmt.Errorf("error when forwarding data to 'less': %w", err)
}
return nil
}
func isErrPipe(err error) bool {
return errors.Is(err, syscall.EPIPE) || errors.Is(err, io.ErrClosedPipe)
}
func ignoreSignals(sigs ...os.Signal) func() {
ch := make(chan os.Signal, 1)
signal.Notify(ch, sigs...)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
for {
_, ok := <-ch
if !ok {
return
}
}
}()
return func() {
signal.Stop(ch)
close(ch)
wg.Wait()
}
}

View File

@@ -1,436 +0,0 @@
package main
import (
"context"
"errors"
"flag"
"fmt"
"io"
"io/fs"
"net/http"
"net/url"
"os"
"os/signal"
"strconv"
"strings"
"syscall"
"time"
"github.com/ergochat/readline"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/buildinfo"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/envflag"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
)
var (
datasourceURL = flag.String("datasource.url", "http://localhost:9428/select/logsql/query", "URL for querying VictoriaLogs; "+
"see https://docs.victoriametrics.com/victorialogs/querying/#querying-logs . See also -tail.url")
tailURL = flag.String("tail.url", "", "URL for live tailing queries to VictoriaLogs; see https://docs.victoriametrics.com/victorialogs/querying/#live-tailing ."+
"The url is automatically detected from -datasource.url by replacing /query with /tail at the end if -tail.url is empty")
historyFile = flag.String("historyFile", "vlogscli-history", "Path to file with command history")
header = flagutil.NewArrayString("header", "Optional header to pass in request -datasource.url in the form 'HeaderName: value'")
accountID = flag.Int("accountID", 0, "Account ID to query; see https://docs.victoriametrics.com/victorialogs/#multitenancy")
projectID = flag.Int("projectID", 0, "Project ID to query; see https://docs.victoriametrics.com/victorialogs/#multitenancy")
)
const (
firstLinePrompt = ";> "
nextLinePrompt = ""
)
func main() {
// Write flags and help message to stdout, since it is easier to grep or pipe.
flag.CommandLine.SetOutput(os.Stdout)
flag.Usage = usage
envflag.Parse()
buildinfo.Init()
logger.InitNoLogFlags()
hes, err := parseHeaders(*header)
if err != nil {
fatalf("cannot parse -header command-line flag: %s", err)
}
headers = hes
incompleteLine := ""
cfg := &readline.Config{
Prompt: firstLinePrompt,
DisableAutoSaveHistory: true,
Listener: func(line []rune, pos int, _ rune) ([]rune, int, bool) {
incompleteLine = string(line)
return line, pos, false
},
}
rl, err := readline.NewFromConfig(cfg)
if err != nil {
fatalf("cannot initialize readline: %s", err)
}
fmt.Fprintf(rl, "sending queries to -datasource.url=%s\n", *datasourceURL)
fmt.Fprintf(rl, `type ? and press enter to see available commands`+"\n")
runReadlineLoop(rl, &incompleteLine)
if err := rl.Close(); err != nil {
fatalf("cannot close readline: %s", err)
}
}
func runReadlineLoop(rl *readline.Instance, incompleteLine *string) {
historyLines, err := loadFromHistory(*historyFile)
if err != nil {
fatalf("cannot load query history: %s", err)
}
for _, line := range historyLines {
if err := rl.SaveToHistory(line); err != nil {
fatalf("cannot initialize query history: %s", err)
}
}
outputMode := outputModeJSONMultiline
wrapLongLines := false
s := ""
for {
line, err := rl.ReadLine()
if err != nil {
switch err {
case io.EOF:
if s != "" {
// This is non-interactive query execution.
executeQuery(context.Background(), rl, s, outputMode, wrapLongLines)
}
return
case readline.ErrInterrupt:
if s == "" && *incompleteLine == "" {
fmt.Fprintf(rl, "interrupted\n")
os.Exit(128 + int(syscall.SIGINT))
}
// Default value for Ctrl+C - clear the prompt and store the incompletely entered line into history
s += *incompleteLine
historyLines = pushToHistory(rl, historyLines, s)
s = ""
rl.SetPrompt(firstLinePrompt)
continue
default:
fatalf("unexpected error in readline: %s", err)
}
}
s += line
if s == "" {
// Skip empty lines
continue
}
if isQuitCommand(s) {
fmt.Fprintf(rl, "bye!\n")
_ = pushToHistory(rl, historyLines, s)
return
}
if isHelpCommand(s) {
printCommandsHelp(rl)
historyLines = pushToHistory(rl, historyLines, s)
s = ""
continue
}
if s == `\s` {
fmt.Fprintf(rl, "singleline json output mode\n")
outputMode = outputModeJSONSingleline
historyLines = pushToHistory(rl, historyLines, s)
s = ""
continue
}
if s == `\m` {
fmt.Fprintf(rl, "multiline json output mode\n")
outputMode = outputModeJSONMultiline
historyLines = pushToHistory(rl, historyLines, s)
s = ""
continue
}
if s == `\c` {
fmt.Fprintf(rl, "compact output mode\n")
outputMode = outputModeCompact
historyLines = pushToHistory(rl, historyLines, s)
s = ""
continue
}
if s == `\logfmt` {
fmt.Fprintf(rl, "logfmt output mode\n")
outputMode = outputModeLogfmt
historyLines = pushToHistory(rl, historyLines, s)
s = ""
continue
}
if s == `\wrap_long_lines` {
if wrapLongLines {
wrapLongLines = false
fmt.Fprintf(rl, "wrapping of long lines is disabled\n")
} else {
wrapLongLines = true
fmt.Fprintf(rl, "wrapping of long lines is enabled\n")
}
historyLines = pushToHistory(rl, historyLines, s)
s = ""
continue
}
if line != "" && !strings.HasSuffix(line, ";") {
// Assume the query is incomplete and allow the user finishing the query on the next line
s += "\n"
rl.SetPrompt(nextLinePrompt)
continue
}
// Execute the query
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
executeQuery(ctx, rl, s, outputMode, wrapLongLines)
cancel()
historyLines = pushToHistory(rl, historyLines, s)
s = ""
rl.SetPrompt(firstLinePrompt)
}
}
func pushToHistory(rl *readline.Instance, historyLines []string, s string) []string {
s = strings.TrimSpace(s)
if len(historyLines) == 0 || historyLines[len(historyLines)-1] != s {
historyLines = append(historyLines, s)
if len(historyLines) > 500 {
historyLines = historyLines[len(historyLines)-500:]
}
if err := saveToHistory(*historyFile, historyLines); err != nil {
fatalf("cannot save query history: %s", err)
}
}
if err := rl.SaveToHistory(s); err != nil {
fatalf("cannot update query history: %s", err)
}
return historyLines
}
func loadFromHistory(filePath string) ([]string, error) {
data, err := os.ReadFile(filePath)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return nil, nil
}
return nil, err
}
linesQuoted := strings.Split(string(data), "\n")
lines := make([]string, 0, len(linesQuoted))
i := 0
for _, lineQuoted := range linesQuoted {
i++
if lineQuoted == "" {
continue
}
line, err := strconv.Unquote(lineQuoted)
if err != nil {
return nil, fmt.Errorf("cannot parse line #%d at %s: %w; line: [%s]", i, filePath, err, line)
}
lines = append(lines, line)
}
return lines, nil
}
func saveToHistory(filePath string, lines []string) error {
linesQuoted := make([]string, len(lines))
for i, line := range lines {
lineQuoted := strconv.Quote(line)
linesQuoted[i] = lineQuoted
}
data := strings.Join(linesQuoted, "\n")
return os.WriteFile(filePath, []byte(data), 0600)
}
func isQuitCommand(s string) bool {
switch s {
case `\q`, "q", "quit", "exit":
return true
default:
return false
}
}
func isHelpCommand(s string) bool {
switch s {
case `\h`, "h", "help", "?":
return true
default:
return false
}
}
func printCommandsHelp(w io.Writer) {
fmt.Fprintf(w, "%s", `Available commands:
\q - quit
\h - show this help
\s - singleline json output mode
\m - multiline json output mode
\c - compact output mode
\logfmt - logfmt output mode
\wrap_long_lines - toggles wrapping long lines
\tail <query> - live tail <query> results
See https://docs.victoriametrics.com/victorialogs/querying/vlogscli/ for more details
`)
}
func executeQuery(ctx context.Context, output io.Writer, qStr string, outputMode outputMode, wrapLongLines bool) {
if strings.HasPrefix(qStr, `\tail `) {
tailQuery(ctx, output, qStr, outputMode)
return
}
respBody := getQueryResponse(ctx, output, qStr, outputMode, *datasourceURL)
if respBody == nil {
return
}
defer func() {
_ = respBody.Close()
}()
if err := readWithLess(respBody, wrapLongLines); err != nil {
fmt.Fprintf(output, "error when reading query response: %s\n", err)
return
}
}
func tailQuery(ctx context.Context, output io.Writer, qStr string, outputMode outputMode) {
qStr = strings.TrimPrefix(qStr, `\tail `)
qURL, err := getTailURL()
if err != nil {
fmt.Fprintf(output, "%s\n", err)
return
}
respBody := getQueryResponse(ctx, output, qStr, outputMode, qURL)
if respBody == nil {
return
}
defer func() {
_ = respBody.Close()
}()
if _, err := io.Copy(output, respBody); err != nil {
if !errors.Is(err, context.Canceled) && !isErrPipe(err) {
fmt.Fprintf(output, "error when live tailing query response: %s\n", err)
}
fmt.Fprintf(output, "\n")
return
}
}
func getTailURL() (string, error) {
if *tailURL != "" {
return *tailURL, nil
}
u, err := url.Parse(*datasourceURL)
if err != nil {
return "", fmt.Errorf("cannot parse -datasource.url=%q: %w", *datasourceURL, err)
}
if !strings.HasSuffix(u.Path, "/query") {
return "", fmt.Errorf("cannot find /query suffix in -datasource.url=%q", *datasourceURL)
}
u.Path = u.Path[:len(u.Path)-len("/query")] + "/tail"
return u.String(), nil
}
func getQueryResponse(ctx context.Context, output io.Writer, qStr string, outputMode outputMode, qURL string) io.ReadCloser {
// Parse the query and convert it to canonical view.
qStr = strings.TrimSuffix(qStr, ";")
q, err := logstorage.ParseQuery(qStr)
if err != nil {
fmt.Fprintf(output, "cannot parse query: %s\n", err)
return nil
}
qStr = q.String()
fmt.Fprintf(output, "executing [%s]...", qStr)
// Prepare HTTP request for qURL
args := make(url.Values)
args.Set("query", qStr)
data := strings.NewReader(args.Encode())
req, err := http.NewRequestWithContext(ctx, "POST", qURL, data)
if err != nil {
panic(fmt.Errorf("BUG: cannot prepare request to server: %w", err))
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
for _, h := range headers {
req.Header.Set(h.Name, h.Value)
}
req.Header.Set("AccountID", strconv.Itoa(*accountID))
req.Header.Set("ProjectID", strconv.Itoa(*projectID))
// Execute HTTP request at qURL
startTime := time.Now()
resp, err := httpClient.Do(req)
queryDuration := time.Since(startTime)
fmt.Fprintf(output, "; duration: %.3fs\n", queryDuration.Seconds())
if err != nil {
if errors.Is(err, context.Canceled) {
fmt.Fprintf(output, "\n")
} else {
fmt.Fprintf(output, "cannot execute query: %s\n", err)
}
return nil
}
// Verify response code
if resp.StatusCode != http.StatusOK {
body, err := io.ReadAll(resp.Body)
if err != nil {
body = []byte(fmt.Sprintf("cannot read response body: %s", err))
}
fmt.Fprintf(output, "unexpected status code: %d; response body:\n%s\n", resp.StatusCode, body)
return nil
}
// Prettify the response body
jp := newJSONPrettifier(resp.Body, outputMode)
return jp
}
var httpClient = &http.Client{}
var headers []headerEntry
type headerEntry struct {
Name string
Value string
}
func parseHeaders(a []string) ([]headerEntry, error) {
hes := make([]headerEntry, len(a))
for i, s := range a {
a := strings.SplitN(s, ":", 2)
if len(a) != 2 {
return nil, fmt.Errorf("cannot parse header=%q; it must contain at least one ':'; for example, 'Cookie: foo'", s)
}
hes[i] = headerEntry{
Name: strings.TrimSpace(a[0]),
Value: strings.TrimSpace(a[1]),
}
}
return hes, nil
}
func fatalf(format string, args ...any) {
fmt.Fprintf(os.Stderr, format+"\n", args...)
os.Exit(1)
}
func usage() {
const s = `
vlogscli is a command-line tool for querying VictoriaLogs.
See the docs at https://docs.victoriametrics.com/victorialogs/querying/vlogscli/
`
flagutil.Usage(s)
}

View File

@@ -1,11 +0,0 @@
# See https://medium.com/on-docker/use-multi-stage-builds-to-inject-ca-certs-ad1e8f01de1b
ARG certs_image=non-existing
ARG root_image=non-existing
FROM $certs_image AS certs
RUN apk update && apk upgrade && apk --update --no-cache add ca-certificates
FROM $root_image
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
ENTRYPOINT ["/vlogscli-prod"]
ARG TARGETARCH
COPY vlogscli-linux-${TARGETARCH}-prod ./vlogscli-prod

View File

@@ -1,7 +0,0 @@
# All these commands must run from repository root.
vlogsgenerator:
APP_NAME=vlogsgenerator $(MAKE) app-local
vlogsgenerator-race:
APP_NAME=vlogsgenerator RACE=-race $(MAKE) app-local

View File

@@ -1,158 +1 @@
# vlogsgenerator
Logs generator for [VictoriaLogs](https://docs.victoriametrics.com/victorialogs/).
## How to build vlogsgenerator?
Run `make vlogsgenerator` from the repository root. This builds `bin/vlogsgenerator` binary.
## How run vlogsgenerator?
`vlogsgenerator` generates logs in [JSON line format](https://jsonlines.org/) suitable for the ingestion
via [`/insert/jsonline` endpoint at VictoriaLogs](https://docs.victoriametrics.com/victorialogs/data-ingestion/#json-stream-api).
By default it writes the generated logs into `stdout`. For example, the following command writes generated logs to `stdout`:
```
bin/vlogsgenerator
```
It is possible to redirect the generated logs to file. For example, the following command writes the generated logs to `logs.json` file:
```
bin/vlogsgenerator > logs.json
```
The generated logs at `logs.json` file can be inspected with the following command:
```
head logs.json | jq .
```
Below is an example output:
```json
{
"_time": "2024-05-08T14:34:00.854Z",
"_msg": "message for the stream 8 and worker 0; ip=185.69.136.129; uuid=b4fe8f1a-c93c-dea3-ba11-5b9f0509291e; u64=8996587920687045253",
"host": "host_8",
"worker_id": "0",
"run_id": "f9b3deee-e6b6-7f56-5deb-1586e4e81725",
"const_0": "some value 0 8",
"const_1": "some value 1 8",
"const_2": "some value 2 8",
"var_0": "some value 0 12752539384823438260",
"dict_0": "warn",
"dict_1": "info",
"u8_0": "6",
"u16_0": "35202",
"u32_0": "1964973739",
"u64_0": "4810489083243239145",
"float_0": "1.868",
"ip_0": "250.34.75.125",
"timestamp_0": "1799-03-16T01:34:18.311Z",
"json_0": "{\"foo\":\"bar_3\",\"baz\":{\"a\":[\"x\",\"y\"]},\"f3\":NaN,\"f4\":32}"
}
{
"_time": "2024-05-08T14:34:00.854Z",
"_msg": "message for the stream 9 and worker 0; ip=164.244.254.194; uuid=7e8373b1-ce0d-1ce7-8e96-4bcab8955598; u64=13949903463741076522",
"host": "host_9",
"worker_id": "0",
"run_id": "f9b3deee-e6b6-7f56-5deb-1586e4e81725",
"const_0": "some value 0 9",
"const_1": "some value 1 9",
"const_2": "some value 2 9",
"var_0": "some value 0 5371555382075206134",
"dict_0": "INFO",
"dict_1": "FATAL",
"u8_0": "219",
"u16_0": "31459",
"u32_0": "3918836777",
"u64_0": "6593354256620219850",
"float_0": "1.085",
"ip_0": "253.151.88.158",
"timestamp_0": "2042-10-05T16:42:57.082Z",
"json_0": "{\"foo\":\"bar_5\",\"baz\":{\"a\":[\"x\",\"y\"]},\"f3\":NaN,\"f4\":27}"
}
```
The `run_id` field uniquely identifies every `vlogsgenerator` invocation.
### How to write logs to VictoriaLogs?
The generated logs can be written directly to VictoriaLogs by passing the address of [`/insert/jsonline` endpoint](https://docs.victoriametrics.com/victorialogs/data-ingestion/#json-stream-api)
to `-addr` command-line flag. For example, the following command writes the generated logs to VictoriaLogs running at `localhost`:
```
bin/vlogsgenerator -addr=http://localhost:9428/insert/jsonline
```
### Configuration
`vlogsgenerator` accepts various command-line flags, which can be used for configuring the number and the shape of the generated logs.
These flags can be inspected by running `vlogsgenerator -help`. Below are the most interesting flags:
* `-start` - starting timestamp for generating logs. Logs are evenly generated on the [`-start` ... `-end`] interval.
* `-end` - ending timestamp for generating logs. Logs are evenly generated on the [`-start` ... `-end`] interval.
* `-activeStreams` - the number of active [log streams](https://docs.victoriametrics.com/victorialogs/keyconcepts/#stream-fields) to generate.
* `-logsPerStream` - the number of log entries to generate per each log stream. Log entries are evenly distributed on the [`-start` ... `-end`] interval.
The total number of generated logs can be calculated as `-activeStreams` * `-logsPerStream`.
For example, the following command generates `1_000_000` log entries on the time range `[2024-01-01 - 2024-02-01]` across `100`
[log streams](https://docs.victoriametrics.com/victorialogs/keyconcepts/#stream-fields), where every logs stream contains `10_000` log entries,
and writes them to `http://localhost:9428/insert/jsonline`:
```
bin/vlogsgenerator \
-start=2024-01-01 -end=2024-02-01 \
-activeStreams=100 \
-logsPerStream=10_000 \
-addr=http://localhost:9428/insert/jsonline
```
### Churn rate
It is possible to generate churn rate for active [log streams](https://docs.victoriametrics.com/victorialogs/keyconcepts/#stream-fields)
by specifying `-totalStreams` command-line flag bigger than `-activeStreams`. For example, the following command generates
logs for `1000` total streams, while the number of active streams equals to `100`. This means that at every time there are logs for `100` streams,
but these streams change over the given [`-start` ... `-end`] time range, so the total number of streams on the given time range becomes `1000`:
```
bin/vlogsgenerator \
-start=2024-01-01 -end=2024-02-01 \
-activeStreams=100 \
-totalStreams=1_000 \
-logsPerStream=10_000 \
-addr=http://localhost:9428/insert/jsonline
```
In this case the total number of generated logs equals to `-totalStreams` * `-logsPerStream` = `10_000_000`.
### Benchmark tuning
By default `vlogsgenerator` generates and writes logs by a single worker. This may limit the maximum data ingestion rate during benchmarks.
The number of workers can be changed via `-workers` command-line flag. For example, the following command generates and writes logs with `16` workers:
```
bin/vlogsgenerator \
-start=2024-01-01 -end=2024-02-01 \
-activeStreams=100 \
-logsPerStream=10_000 \
-addr=http://localhost:9428/insert/jsonline \
-workers=16
```
### Output statistics
Every 10 seconds `vlogsgenerator` writes statistics about the generated logs into `stderr`. The frequency of the generated statistics can be adjusted via `-statInterval` command-line flag.
For example, the following command writes statistics every 2 seconds:
```
bin/vlogsgenerator \
-start=2024-01-01 -end=2024-02-01 \
-activeStreams=100 \
-logsPerStream=10_000 \
-addr=http://localhost:9428/insert/jsonline \
-statInterval=2s
```
VictoriaLogs source code has been moved to [github.com/VictoriaMetrics/VictoriaLogs](https://github.com/VictoriaMetrics/VictoriaLogs/).

View File

@@ -1,352 +0,0 @@
package main
import (
"bufio"
"flag"
"fmt"
"io"
"math"
"math/rand"
"net/http"
"net/url"
"os"
"strconv"
"sync"
"sync/atomic"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/buildinfo"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/envflag"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/timeutil"
)
var (
addr = flag.String("addr", "stdout", "HTTP address to push the generated logs to; if it is set to stdout, then logs are generated to stdout")
workers = flag.Int("workers", 1, "The number of workers to use to push logs to -addr")
start = newTimeFlag("start", "-1d", "Generated logs start from this time; see https://docs.victoriametrics.com/#timestamp-formats")
end = newTimeFlag("end", "0s", "Generated logs end at this time; see https://docs.victoriametrics.com/#timestamp-formats")
activeStreams = flag.Int("activeStreams", 100, "The number of active log streams to generate; see https://docs.victoriametrics.com/victorialogs/keyconcepts/#stream-fields")
totalStreams = flag.Int("totalStreams", 0, "The number of total log streams; if -totalStreams > -activeStreams, then some active streams are substituted with new streams "+
"during data generation")
logsPerStream = flag.Int64("logsPerStream", 1_000, "The number of log entries to generate per each log stream. Log entries are evenly distributed between -start and -end")
constFieldsPerLog = flag.Int("constFieldsPerLog", 3, "The number of fields with constant values to generate per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
varFieldsPerLog = flag.Int("varFieldsPerLog", 1, "The number of fields with variable values to generate per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
dictFieldsPerLog = flag.Int("dictFieldsPerLog", 2, "The number of fields with up to 8 different values to generate per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
u8FieldsPerLog = flag.Int("u8FieldsPerLog", 1, "The number of fields with uint8 values to generate per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
u16FieldsPerLog = flag.Int("u16FieldsPerLog", 1, "The number of fields with uint16 values to generate per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
u32FieldsPerLog = flag.Int("u32FieldsPerLog", 1, "The number of fields with uint32 values to generate per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
u64FieldsPerLog = flag.Int("u64FieldsPerLog", 1, "The number of fields with uint64 values to generate per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
i64FieldsPerLog = flag.Int("i64FieldsPerLog", 1, "The number of fields with int64 values to generate per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
floatFieldsPerLog = flag.Int("floatFieldsPerLog", 1, "The number of fields with float64 values to generate per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
ipFieldsPerLog = flag.Int("ipFieldsPerLog", 1, "The number of fields with IPv4 values to generate per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
timestampFieldsPerLog = flag.Int("timestampFieldsPerLog", 1, "The number of fields with ISO8601 timestamps per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
jsonFieldsPerLog = flag.Int("jsonFieldsPerLog", 1, "The number of JSON fields to generate per each log entry; "+
"see https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model")
statInterval = flag.Duration("statInterval", 10*time.Second, "The interval between publishing the stats")
)
func main() {
// Write flags and help message to stdout, since it is easier to grep or pipe.
flag.CommandLine.SetOutput(os.Stdout)
envflag.Parse()
buildinfo.Init()
logger.Init()
var remoteWriteURL *url.URL
if *addr != "stdout" {
urlParsed, err := url.Parse(*addr)
if err != nil {
logger.Fatalf("cannot parse -addr=%q: %s", *addr, err)
}
qs, err := url.ParseQuery(urlParsed.RawQuery)
if err != nil {
logger.Fatalf("cannot parse query string in -addr=%q: %w", *addr, err)
}
qs.Set("_stream_fields", "host,worker_id")
urlParsed.RawQuery = qs.Encode()
remoteWriteURL = urlParsed
}
if start.nsec >= end.nsec {
logger.Fatalf("-start=%s must be smaller than -end=%s", start, end)
}
if *activeStreams <= 0 {
logger.Fatalf("-activeStreams must be bigger than 0; got %d", *activeStreams)
}
if *logsPerStream <= 0 {
logger.Fatalf("-logsPerStream must be bigger than 0; got %d", *logsPerStream)
}
if *totalStreams < *activeStreams {
*totalStreams = *activeStreams
}
cfg := &workerConfig{
url: remoteWriteURL,
activeStreams: *activeStreams,
totalStreams: *totalStreams,
}
// divide total and active streams among workers
if *workers <= 0 {
logger.Fatalf("-workers must be bigger than 0; got %d", *workers)
}
if *workers > *activeStreams {
logger.Fatalf("-workers=%d cannot exceed -activeStreams=%d", *workers, *activeStreams)
}
cfg.activeStreams /= *workers
cfg.totalStreams /= *workers
logger.Infof("start -workers=%d workers for ingesting -logsPerStream=%d log entries per each -totalStreams=%d (-activeStreams=%d) on a time range -start=%s, -end=%s to -addr=%s",
*workers, *logsPerStream, *totalStreams, *activeStreams, toRFC3339(start.nsec), toRFC3339(end.nsec), *addr)
startTime := time.Now()
var wg sync.WaitGroup
for i := 0; i < *workers; i++ {
wg.Add(1)
go func(workerID int) {
defer wg.Done()
generateAndPushLogs(cfg, workerID)
}(i)
}
go func() {
prevEntries := uint64(0)
prevBytes := uint64(0)
ticker := time.NewTicker(*statInterval)
for range ticker.C {
currEntries := logEntriesCount.Load()
deltaEntries := currEntries - prevEntries
rateEntries := float64(deltaEntries) / statInterval.Seconds()
currBytes := bytesGenerated.Load()
deltaBytes := currBytes - prevBytes
rateBytes := float64(deltaBytes) / statInterval.Seconds()
logger.Infof("generated %dK log entries (%dK total) at %.0fK entries/sec, %dMB (%dMB total) at %.0fMB/sec",
deltaEntries/1e3, currEntries/1e3, rateEntries/1e3, deltaBytes/1e6, currBytes/1e6, rateBytes/1e6)
prevEntries = currEntries
prevBytes = currBytes
}
}()
wg.Wait()
dSecs := time.Since(startTime).Seconds()
currEntries := logEntriesCount.Load()
currBytes := bytesGenerated.Load()
rateEntries := float64(currEntries) / dSecs
rateBytes := float64(currBytes) / dSecs
logger.Infof("ingested %dK log entries (%dMB) in %.3f seconds; avg ingestion rate: %.0fK entries/sec, %.0fMB/sec", currEntries/1e3, currBytes/1e6, dSecs, rateEntries/1e3, rateBytes/1e6)
}
var logEntriesCount atomic.Uint64
var bytesGenerated atomic.Uint64
type workerConfig struct {
url *url.URL
activeStreams int
totalStreams int
}
type statWriter struct {
w io.Writer
}
func (sw *statWriter) Write(p []byte) (int, error) {
bytesGenerated.Add(uint64(len(p)))
return sw.w.Write(p)
}
func generateAndPushLogs(cfg *workerConfig, workerID int) {
pr, pw := io.Pipe()
sw := &statWriter{
w: pw,
}
// The 1MB write buffer increases data ingestion performance by reducing the number of send() syscalls
bw := bufio.NewWriterSize(sw, 1024*1024)
doneCh := make(chan struct{})
go func() {
generateLogs(bw, workerID, cfg.activeStreams, cfg.totalStreams)
_ = bw.Flush()
_ = pw.Close()
close(doneCh)
}()
if cfg.url == nil {
_, err := io.Copy(os.Stdout, pr)
if err != nil {
logger.Fatalf("unexpected error when writing logs to stdout: %s", err)
}
return
}
req, err := http.NewRequest("POST", cfg.url.String(), pr)
if err != nil {
logger.Fatalf("cannot create request to %q: %s", cfg.url, err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
logger.Fatalf("cannot perform request to %q: %s", cfg.url, err)
}
if resp.StatusCode/100 != 2 {
logger.Fatalf("unexpected status code got from %q: %d; want 2xx", cfg.url, err)
}
// Wait until all the generateLogs goroutine is finished.
<-doneCh
}
func generateLogs(bw *bufio.Writer, workerID, activeStreams, totalStreams int) {
streamLifetime := int64(float64(end.nsec-start.nsec) * (float64(activeStreams) / float64(totalStreams)))
streamStep := int64(float64(end.nsec-start.nsec) / float64(totalStreams-activeStreams+1))
step := streamLifetime / (*logsPerStream - 1)
currNsec := start.nsec
for currNsec < end.nsec {
firstStreamID := int((currNsec - start.nsec) / streamStep)
generateLogsAtTimestamp(bw, workerID, currNsec, firstStreamID, activeStreams)
currNsec += step
}
}
var runID = toUUID(rand.Uint64(), rand.Uint64())
func generateLogsAtTimestamp(bw *bufio.Writer, workerID int, ts int64, firstStreamID, activeStreams int) {
streamID := firstStreamID
timeStr := toRFC3339(ts)
for i := 0; i < activeStreams; i++ {
ip := toIPv4(rand.Uint32())
uuid := toUUID(rand.Uint64(), rand.Uint64())
fmt.Fprintf(bw, `{"_time":"%s","_msg":"message for the stream %d and worker %d; ip=%s; uuid=%s; u64=%d","host":"host_%d","worker_id":"%d"`,
timeStr, streamID, workerID, ip, uuid, rand.Uint64(), streamID, workerID)
fmt.Fprintf(bw, `,"run_id":"%s"`, runID)
for j := 0; j < *constFieldsPerLog; j++ {
fmt.Fprintf(bw, `,"const_%d":"some value %d %d"`, j, j, streamID)
}
for j := 0; j < *varFieldsPerLog; j++ {
fmt.Fprintf(bw, `,"var_%d":"some value %d %d"`, j, j, rand.Uint64())
}
for j := 0; j < *dictFieldsPerLog; j++ {
fmt.Fprintf(bw, `,"dict_%d":"%s"`, j, dictValues[rand.Intn(len(dictValues))])
}
for j := 0; j < *u8FieldsPerLog; j++ {
fmt.Fprintf(bw, `,"u8_%d":"%d"`, j, uint8(rand.Uint32()))
}
for j := 0; j < *u16FieldsPerLog; j++ {
fmt.Fprintf(bw, `,"u16_%d":"%d"`, j, uint16(rand.Uint32()))
}
for j := 0; j < *u32FieldsPerLog; j++ {
fmt.Fprintf(bw, `,"u32_%d":"%d"`, j, rand.Uint32())
}
for j := 0; j < *u64FieldsPerLog; j++ {
fmt.Fprintf(bw, `,"u64_%d":"%d"`, j, rand.Uint64())
}
for j := 0; j < *i64FieldsPerLog; j++ {
fmt.Fprintf(bw, `,"i64_%d":"%d"`, j, int64(rand.Uint64()))
}
for j := 0; j < *floatFieldsPerLog; j++ {
fmt.Fprintf(bw, `,"float_%d":"%v"`, j, math.Round(10_000*rand.Float64())/1000)
}
for j := 0; j < *ipFieldsPerLog; j++ {
ip := toIPv4(rand.Uint32())
fmt.Fprintf(bw, `,"ip_%d":"%s"`, j, ip)
}
for j := 0; j < *timestampFieldsPerLog; j++ {
timestamp := toISO8601(int64(rand.Uint64()))
fmt.Fprintf(bw, `,"timestamp_%d":"%s"`, j, timestamp)
}
for j := 0; j < *jsonFieldsPerLog; j++ {
fmt.Fprintf(bw, `,"json_%d":"{\"foo\":\"bar_%d\",\"baz\":{\"a\":[\"x\",\"y\"]},\"f3\":NaN,\"f4\":%d}"`, j, rand.Intn(10), rand.Intn(100))
}
fmt.Fprintf(bw, "}\n")
logEntriesCount.Add(1)
streamID++
}
}
var dictValues = []string{
"debug",
"info",
"warn",
"error",
"fatal",
"ERROR",
"FATAL",
"INFO",
}
func newTimeFlag(name, defaultValue, description string) *timeFlag {
var tf timeFlag
if err := tf.Set(defaultValue); err != nil {
logger.Panicf("invalid defaultValue=%q for flag %q: %w", defaultValue, name, err)
}
flag.Var(&tf, name, description)
return &tf
}
type timeFlag struct {
s string
nsec int64
}
func (tf *timeFlag) Set(s string) error {
msec, err := timeutil.ParseTimeMsec(s)
if err != nil {
return fmt.Errorf("cannot parse time from %q: %w", s, err)
}
tf.s = s
tf.nsec = msec * 1e6
return nil
}
func (tf *timeFlag) String() string {
return tf.s
}
func toRFC3339(nsec int64) string {
return time.Unix(0, nsec).UTC().Format(time.RFC3339Nano)
}
func toISO8601(nsec int64) string {
return time.Unix(0, nsec).UTC().Format("2006-01-02T15:04:05.000Z")
}
func toIPv4(n uint32) string {
dst := make([]byte, 0, len("255.255.255.255"))
dst = marshalUint64(dst, uint64(n>>24))
dst = append(dst, '.')
dst = marshalUint64(dst, uint64((n>>16)&0xff))
dst = append(dst, '.')
dst = marshalUint64(dst, uint64((n>>8)&0xff))
dst = append(dst, '.')
dst = marshalUint64(dst, uint64(n&0xff))
return string(dst)
}
func toUUID(a, b uint64) string {
return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x", a&(1<<32-1), (a>>32)&(1<<16-1), (a >> 48), b&(1<<16-1), b>>16)
}
// marshalUint64 appends string representation of n to dst and returns the result.
func marshalUint64(dst []byte, n uint64) []byte {
return strconv.AppendUint(dst, n, 10)
}

1
app/vlselect/README.md Normal file
View File

@@ -0,0 +1 @@
VictoriaLogs source code has been moved to [github.com/VictoriaMetrics/VictoriaLogs](https://github.com/VictoriaMetrics/VictoriaLogs/).

View File

@@ -1,47 +0,0 @@
package logsql
import (
"bufio"
"io"
"sync"
)
func getBufferedWriter(w io.Writer) *bufferedWriter {
v := bufferedWriterPool.Get()
if v == nil {
return &bufferedWriter{
bw: bufio.NewWriter(w),
}
}
bw := v.(*bufferedWriter)
bw.bw.Reset(w)
return bw
}
func putBufferedWriter(bw *bufferedWriter) {
bw.reset()
bufferedWriterPool.Put(bw)
}
var bufferedWriterPool sync.Pool
type bufferedWriter struct {
mu sync.Mutex
bw *bufio.Writer
}
func (bw *bufferedWriter) reset() {
// nothing to do
}
func (bw *bufferedWriter) WriteIgnoreErrors(p []byte) {
bw.mu.Lock()
_, _ = bw.bw.Write(p)
bw.mu.Unlock()
}
func (bw *bufferedWriter) FlushIgnoreErrors() {
bw.mu.Lock()
_ = bw.bw.Flush()
bw.mu.Unlock()
}

View File

@@ -1,49 +0,0 @@
{% import (
"slices"
) %}
{% stripspace %}
{% func FacetsResponse(m map[string][]facetEntry) %}
{
{% code
sortedKeys := make([]string, 0, len(m))
for k := range m {
sortedKeys = append(sortedKeys, k)
}
slices.Sort(sortedKeys)
%}
"facets":[
{% if len(sortedKeys) > 0 %}
{%= facetsLine(m, sortedKeys[0]) %}
{% for _, k := range sortedKeys[1:] %}
,{%= facetsLine(m, k) %}
{% endfor %}
{% endif %}
]
}
{% endfunc %}
{% func facetsLine(m map[string][]facetEntry, k string) %}
{
"field_name":{%q= k %},
"values":[
{% code fes := m[k] %}
{% if len(fes) > 0 %}
{%= facetLine(fes[0]) %}
{% for _, fe := range fes[1:] %}
,{%= facetLine(fe) %}
{% endfor %}
{% endif %}
]
}
{% endfunc %}
{% func facetLine(fe facetEntry) %}
{
"field_value":{%q= fe.value %},
"hits":{%s= fe.hits %}
}
{% endfunc %}
{% endstripspace %}

Some files were not shown because too many files have changed in this diff Show More