Telegraf Enterprise / Telegraf Controller Beta (#6990)

* chore(telegraf_controller): base template and layout changes for telegraf controller beta (#6921)

* feat(tc-users): telegraf controller manage users docs (#6924)

* feat(tc-auth): telegraf controller authorization reference doc (#6923)

* feat(tc-auth): telegraf controller authorization reference doc

* chore(tc-auth): minor update to telegraf controller auth reference

* chore(tc-auth): minor update to telegraf controller auth reference

* feat(tc-settings): add settings page for telegraf controller (#6928)

* feat(tc-settings): add settings page for telegraf controller

* Apply suggestions from code review

Co-authored-by: Jason Stirnaman <stirnamanj@gmail.com>

* Apply suggestion from @sanderson

---------

Co-authored-by: Jason Stirnaman <stirnamanj@gmail.com>

* chore(tc-tokens): add API token docs for telegraf controller (#6927)

* chore(tc-tokens): update code placeholder syntax

* Apply suggestions from code review

Co-authored-by: Jason Stirnaman <stirnamanj@gmail.com>

---------

Co-authored-by: Jason Stirnaman <stirnamanj@gmail.com>

* chore(tc-install): add owner setup to telegraf controller install docs (#6929)

* chore(tc-ownership): update telegraf controller ownership transfer instructions

* feat(tc-download): add gated download for telegraf controller (#6940)

* feat(tc-download): add gated download for telegraf controller

* test(tc-download): add Cypress E2E tests for gated downloads

Cover four key behaviors: gated state (no localStorage key), ungated
state (key present), query param flow (?ref=tc), and SHA copy buttons.

---------

Co-authored-by: Jason Stirnaman <jstirnaman@influxdata.com>

* feat(tc-release-notes): add Telegraf Controller release notes (#6959)

* chore(tc-images): update images for telegraf controller beta

* Tc heartbeat status (#6964)

* feat(tc-cel): add CEL expressions reference documentation

Add multi-page CEL expression reference under Telegraf Controller
reference docs with variables, functions, operators, and examples.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(tc-status): expand agent status page with CEL examples and configuration

Replace stub status page with practical guide including status values,
evaluation overview, three inline config examples, and links to CEL reference.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(tc-heartbeat-status): update status evaluation docs

* chore(tc-heartbeat-status): remove impl plans

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(tc-beta): obfuscate dl URLs

* chore(tc-feedback): add feedback channels to special state partial

* feat(tc-beta): add telegraf enterprise beta notification

* chore(tc-beta): fix typo in tc beta notification

* chore(tc-misc): update code examples, add important info

* feat(tc-beta): added tc 0.0.5-beta download shas

* chore(tc-beta): add tc 0.0.5-beta release notes (#6988)

* chore(tc-beta): add tc 0.0.5-beta release notes, update tc dynamic values highlighting impl

* chore(tc-beta): add download link to release notes

* feat(tc-beta): add tc 0.0.5-beta linux arm download

* fix(tc-beta): fix tc link on homepage

---------

Co-authored-by: Jason Stirnaman <stirnamanj@gmail.com>
Co-authored-by: Jason Stirnaman <jstirnaman@influxdata.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pull/6986/merge
Scott Anderson 2026-03-26 08:20:04 -06:00 committed by GitHub
parent e811a65747
commit ba32cd2a2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
55 changed files with 3110 additions and 94 deletions

View File

@ -0,0 +1,92 @@
/**
* Highlights Telegraf Controller dynamic values in code blocks.
*
* Wraps three pattern types in styled <span> elements:
* - Parameters: &{name} or &{name:default}
* - Environment variables: ${VAR_NAME}
* - Secrets: @{store:secret_name}
*
* Applied to code blocks with class="tc-dynamic-values" via
* the data-component="tc-dynamic-values" attribute set by
* the render-codeblock hook.
*/
const PATTERNS = [
{ regex: /&\{[^}]+\}/g, className: 'param' },
{ regex: /\$\{[^}]+\}/g, className: 'env' },
{ regex: /@\{[^:]+:[^}]+\}/g, className: 'secret' },
];
/**
* Walk all text nodes inside the given element and wrap matches
* in <span class="tc-dynamic-value {type}"> elements.
*/
function highlightDynamicValues(codeEl) {
const walker = document.createTreeWalker(codeEl, NodeFilter.SHOW_TEXT);
const textNodes = [];
while (walker.nextNode()) {
textNodes.push(walker.currentNode);
}
for (const node of textNodes) {
const text = node.textContent;
let hasMatch = false;
for (const { regex } of PATTERNS) {
regex.lastIndex = 0;
if (regex.test(text)) {
hasMatch = true;
break;
}
}
if (!hasMatch) continue;
const fragment = document.createDocumentFragment();
let remaining = text;
while (remaining.length > 0) {
let earliestMatch = null;
let earliestIndex = remaining.length;
let matchedPattern = null;
for (const pattern of PATTERNS) {
pattern.regex.lastIndex = 0;
const match = pattern.regex.exec(remaining);
if (match && match.index < earliestIndex) {
earliestMatch = match;
earliestIndex = match.index;
matchedPattern = pattern;
}
}
if (!earliestMatch) {
fragment.appendChild(document.createTextNode(remaining));
break;
}
if (earliestIndex > 0) {
fragment.appendChild(
document.createTextNode(remaining.slice(0, earliestIndex))
);
}
const span = document.createElement('span');
span.className = `tc-dynamic-value ${matchedPattern.className}`;
span.textContent = earliestMatch[0];
fragment.appendChild(span);
remaining = remaining.slice(earliestIndex + earliestMatch[0].length);
}
node.parentNode.replaceChild(fragment, node);
}
}
export default function TcDynamicValues({ component }) {
const codeEl = component.querySelector('code');
if (codeEl) {
highlightDynamicValues(codeEl);
}
}

View File

@ -122,7 +122,7 @@ function expandAccordions() {
// Expand accordions on load based on URL anchor
function openAccordionByHash() {
var anchor = window.location.hash;
var anchor = window.location.hash.split('?')[0];
function expandElement() {
if ($(anchor).parents('.expand').length > 0) {

View File

@ -19,6 +19,7 @@ import * as pageContext from './page-context.js';
import * as pageFeedback from './page-feedback.js';
import * as tabbedContent from './tabbed-content.js';
import * as v3Wayfinding from './v3-wayfinding.js';
import * as tcDownloads from './tc-downloads.js';
/** Import component modules
* The component pattern organizes JavaScript, CSS, and HTML for a specific UI element or interaction:
@ -44,6 +45,7 @@ import ReleaseToc from './release-toc.js';
import { SearchButton } from './search-button.js';
import SidebarSearch from './components/sidebar-search.js';
import { SidebarToggle } from './sidebar-toggle.js';
import TcDynamicValues from './components/tc-dynamic-values.js';
import Theme from './theme.js';
import ThemeSwitch from './theme-switch.js';
@ -75,6 +77,7 @@ const componentRegistry = {
'search-button': SearchButton,
'sidebar-search': SidebarSearch,
'sidebar-toggle': SidebarToggle,
'tc-dynamic-values': TcDynamicValues,
theme: Theme,
'theme-switch': ThemeSwitch,
};
@ -162,6 +165,7 @@ function initModules() {
pageFeedback.initialize();
tabbedContent.initialize();
v3Wayfinding.initialize();
tcDownloads.initialize();
}
/**

221
assets/js/tc-downloads.js Normal file
View File

@ -0,0 +1,221 @@
////////////////////////////////////////////////////////////////////////////////
///////////////// Telegraf Controller gated downloads module ////////////////////
////////////////////////////////////////////////////////////////////////////////
import { toggleModal } from './modals.js';
const STORAGE_KEY = 'influxdata_docs_tc_dl';
const QUERY_PARAM = 'ref';
const QUERY_VALUE = 'tc';
// ─── localStorage helpers ───────────────────────────────────────────────────
function setDownloadKey() {
localStorage.setItem(STORAGE_KEY, 'true');
}
function hasDownloadKey() {
return localStorage.getItem(STORAGE_KEY) === 'true';
}
// ─── Query param helpers ────────────────────────────────────────────────────
function hasRefParam() {
// Check query string first (?ref=tc before the hash)
const params = new URLSearchParams(window.location.search);
if (params.get(QUERY_PARAM) === QUERY_VALUE) return true;
// Also check inside the fragment (#heading?ref=tc)
const hash = window.location.hash;
const qIndex = hash.indexOf('?');
if (qIndex !== -1) {
const hashParams = new URLSearchParams(hash.substring(qIndex));
if (hashParams.get(QUERY_PARAM) === QUERY_VALUE) return true;
}
return false;
}
function stripRefParam() {
const url = new URL(window.location.href);
// Remove from query string
url.searchParams.delete(QUERY_PARAM);
// Remove from fragment if present (#heading?ref=tc → #heading)
let hash = url.hash;
const qIndex = hash.indexOf('?');
if (qIndex !== -1) {
const hashBase = hash.substring(0, qIndex);
const hashParams = new URLSearchParams(hash.substring(qIndex));
hashParams.delete(QUERY_PARAM);
const remaining = hashParams.toString();
hash = remaining ? `${hashBase}?${remaining}` : hashBase;
}
window.history.replaceState({}, '', url.pathname + url.search + hash);
}
// ─── Download link rendering ────────────────────────────────────────────────
function renderDownloadLinks(container, data) {
const version = data.version;
const platforms = data.platforms;
let html = '<div class="tc-downloads-container">';
platforms.forEach((platform) => {
html += `<h3>${platform.name}</h3>`;
html +=
'<p class="tc-version">' +
`<em>Telegraf Controller v${version}</em>` +
'</p>';
html += '<div class="tc-build-table">';
platform.builds.forEach((build) => {
const link =
`<a href="${build.url}"` +
' class="btn tc-download-link download"' +
` download>${platform.name}` +
` (${build.arch})</a>`;
const sha =
`<code>sha256:${build.sha256}</code>` +
'<button class="tc-copy-sha"' +
` data-sha="${build.sha256}">` +
'&#59693;</button>';
html +=
'<div class="tc-build-row">' +
`<div class="tc-build-download">${link}</div>` +
`<div class="tc-build-sha">${sha}</div>` +
'</div>';
});
html += '</div>';
});
container.innerHTML = html;
}
// ─── Clipboard copy ─────────────────────────────────────────────────────────
function copyToClipboard(sha, button) {
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(sha).then(() => {
showCopiedFeedback(button);
});
} else {
// Fallback for older browsers
const textArea = document.createElement('textarea');
textArea.value = sha;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
showCopiedFeedback(button);
}
}
function showCopiedFeedback(button) {
const original = button.innerHTML;
button.innerHTML = '&#59671;';
setTimeout(() => {
button.innerHTML = original;
}, 2000);
}
// ─── Marketo form ───────────────────────────────────────────────────────────
function initMarketoForm() {
/* global MktoForms2 */
if (typeof MktoForms2 === 'undefined') {
console.error('tc-downloads: MktoForms2 not loaded');
return;
}
MktoForms2.setOptions({
formXDPath: '/rs/972-GDU-533/images/marketo-xdframe-relative.html',
});
MktoForms2.loadForm(
'https://get.influxdata.com',
'972-GDU-533',
3195,
function (form) {
form.addHiddenFields({ mkto_content_name: 'Telegraf Enterprise Alpha' });
form.onSuccess(function () {
setDownloadKey();
toggleModal();
// Redirect to self with ?ref=tc to trigger downloads on reload
const url = new URL(window.location.href);
url.searchParams.set(QUERY_PARAM, QUERY_VALUE);
window.location.href = url.toString();
// Prevent Marketo's default redirect
return false;
});
}
);
}
// ─── View state management ──────────────────────────────────────────────────
function showDownloads(area) {
const btn = area.querySelector('#tc-download-btn');
const linksContainer = area.querySelector('#tc-downloads-links');
if (!linksContainer) return;
// Parse download data from the JSON data attribute
const rawData = linksContainer.getAttribute('data-downloads');
if (!rawData) return;
let data;
try {
data = JSON.parse(atob(rawData));
} catch (e) {
console.error('tc-downloads: failed to parse download data', e);
return;
}
// Hide the download button
if (btn) btn.style.display = 'none';
// Render download links and show the container
renderDownloadLinks(linksContainer, data);
linksContainer.style.display = 'block';
}
// ─── Initialize ─────────────────────────────────────────────────────────────
function initialize() {
// 1. Handle ?ref=tc query param on any page
if (hasRefParam()) {
setDownloadKey();
stripRefParam();
}
const area = document.getElementById('tc-downloads-area');
if (!area) return; // No shortcode on this page — no-op
// 2. Check localStorage and show appropriate view
if (hasDownloadKey()) {
showDownloads(area);
}
// 3. Initialize Marketo form
initMarketoForm();
// 4. Delegated click handler for SHA copy buttons
area.addEventListener('click', function (e) {
const copyBtn = e.target.closest('.tc-copy-sha');
if (copyBtn) {
const sha = copyBtn.getAttribute('data-sha');
if (sha) copyToClipboard(sha, copyBtn);
}
});
}
export { initialize };

View File

@ -216,6 +216,7 @@
"article/tabbed-content",
"article/tables",
"article/tags",
"article/tc-downloads",
"article/telegraf-plugins",
"article/title",
"article/truncate",

View File

@ -278,8 +278,8 @@
position: relative;
overflow: hidden;
display: flex;
flex-direction: row;
align-items: center;
flex-direction: column;
// align-items: center;
justify-content: space-between;
.bg-overlay {
@ -302,9 +302,6 @@
}
ul.product-links {
padding-left: 0;
margin: 0 3rem 0 2rem;
list-style: none;
li:not(:last-child) {margin-bottom: .35rem;}

View File

@ -135,7 +135,8 @@
@import "modals/url-selector";
@import "modals/page-feedback";
@import "modals/flux-versions";
@import "modals/_influxdb-gs-datepicker"
@import "modals/_influxdb-gs-datepicker";
@import "modals/tc-downloads";
}

View File

@ -0,0 +1,104 @@
/////////////////// Styles for inline TC download links ////////////////////////
#tc-downloads-area {
margin: 0 0 2rem;
#tc-download-btn {
display: inline-block;
}
.tc-version {
font-size: 1rem;
color: rgba($article-text, .6);
margin-bottom: .5rem;
}
.tc-build-table {
margin-bottom: 1rem;
}
.tc-build-row {
display: flex;
align-items: center;
border-bottom: 1px solid $article-hr;
&:first-child {
border-top: 1px solid $article-hr;
}
}
.tc-build-download {
flex: 1 1 auto;
margin-right: 1rem;
}
.tc-download-link {
font-size: 1rem;
padding: .35rem 1rem;
white-space: nowrap;
}
.tc-build-sha {
flex: 1 1 auto;
display: flex;
justify-content: flex-end;
gap: .1rem;
min-width: 0;
max-width: 25rem;
code {
font-size: .8rem;
padding: .15rem .65rem;
color: $article-code;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tc-copy-sha {
flex-shrink: 0;
background: $article-code-bg;
border: none;
border-radius: $radius;
padding: .2rem .6rem;
font-family: 'icomoon-v4';
font-size: .9rem;
color: rgba($article-code, .85);
cursor: pointer;
transition: color .2s;
&:hover {
color: $article-code-link-hover;
}
}
}
}
//////////////////////////////// MEDIA QUERIES /////////////////////////////////
@include media(small) {
#tc-downloads-area {
.tc-build-row {
flex-direction: column;
align-items: flex-start;
gap: .5rem;
}
.tc-build-download {
margin-right: 0;
width: 100%;
}
.tc-download-link {
width: 100%;
text-align: center;
}
.tc-build-sha {
width: 100%;
max-width: 100%;
margin-bottom: .5rem;
}
}
}

View File

@ -0,0 +1,226 @@
////////////////////// Styles for the TC downloads modal ////////////////////////
#tc-downloads {
// Reset Marketo's inline styles and defaults ────────────────────────────
.mktoForm {
width: 100% !important;
font-family: $proxima !important;
font-size: 1rem !important;
color: $article-text !important;
padding: 0 !important;
}
// Hide Marketo's offset/gutter spacers
.mktoOffset,
.mktoGutter {
display: none !important;
}
// Form layout: 2-column grid for first 4 fields
.mktoForm {
display: grid !important;
grid-template-columns: 1fr 1fr;
gap: 0 1.75rem;
}
// Visible field rows (First Name, Last Name, Company, Job Title)
// occupy one grid cell each pairs share a row automatically
.mktoFormRow {
margin-bottom: .5rem;
}
// Hidden field rows collapse they don't disrupt the grid
.mktoFormRow:has(input[type='hidden']) {
display: none;
}
// Email, Privacy, and Submit span full width
.mktoFormRow:has(.mktoEmailField),
.mktoFormRow:has(.mktoCheckboxList),
.mktoButtonRow {
grid-column: 1 / -1;
}
.mktoFieldDescriptor,
.mktoFieldWrap {
width: 100% !important;
margin-bottom: 0 !important;
}
// Labels
.mktoLabel {
display: flex !important;
align-items: baseline;
width: 100% !important;
font-family: $proxima !important;
font-weight: $medium !important;
font-size: .9rem !important;
color: $article-bold !important;
padding: .5rem 0 .1rem !important;
}
.mktoAsterix {
order: 1;
color: #e85b5b !important;
float: none !important;
padding-left: .15rem;
}
// Text inputs
.mktoField.mktoTextField,
.mktoField.mktoEmailField {
width: 100% !important;
font-family: $proxima !important;
font-weight: $medium !important;
font-size: 1rem !important;
background: rgba($article-text, .06) !important;
border-radius: $radius !important;
border: 1px solid rgba($article-text, .06) !important;
padding: .5em !important;
color: $article-text !important;
transition-property: border;
transition-duration: .2s;
box-shadow: none !important;
&:focus {
outline: none !important;
border-color: $sidebar-search-highlight !important;
}
&::placeholder {
color: rgba($sidebar-search-text, .45) !important;
font-weight: normal !important;
font-style: italic !important;
}
}
// Checkbox / privacy consent
.mktoFormRow:has(.mktoCheckboxList) .mktoAsterix {
display: none !important;
}
.mktoCheckboxList {
width: 100% !important;
label {
font-family: $proxima !important;
font-size: .85rem !important;
line-height: 1.4 !important;
color: rgba($article-text, .7) !important;
&::after {
content: '*';
color: #e85b5b;
font-weight: $medium;
font-size: .95rem;
font-style: normal;
}
a {
color: $article-link !important;
font-weight: $medium;
text-decoration: none;
transition: color .2s;
&:hover {
color: $article-link-hover !important;
}
}
}
input[type='checkbox'] {
margin: .2rem .65rem 0 0;
}
}
// Submit button
.mktoButtonRow {
margin-top: 1rem;
display: flex;
justify-content: flex-end;
}
.mktoButtonWrap {
margin-left: 0 !important;
}
.mktoButton {
@include gradient($article-btn-gradient);
border: none !important;
border-radius: $radius !important;
padding: .65rem 1.5rem !important;
font-family: $proxima !important;
font-weight: $medium !important;
font-size: 1rem !important;
color: $g20-white !important;
cursor: pointer;
transition: opacity .2s;
&:hover {
@include gradient($article-btn-gradient-hover);
}
}
// Validation errors
// Marketo positions errors absolutely make them flow inline instead
.mktoFieldWrap {
position: relative;
}
.mktoError {
position: relative !important;
bottom: auto !important;
left: auto !important;
right: auto !important;
pointer-events: none;
.mktoErrorArrow {
display: none !important;
}
.mktoErrorMsg {
font-family: $proxima !important;
font-size: .8rem !important;
max-width: 100% !important;
background: none !important;
border: none !important;
color: #e85b5b !important;
padding: .15rem 0 0 !important;
box-shadow: none !important;
text-shadow: none !important;
}
}
// Custom error message
.tc-form-error {
margin: .75rem 0;
padding: .5rem .75rem;
background: rgba(#e85b5b, .1);
border: 1px solid rgba(#e85b5b, .3);
border-radius: $radius;
color: #e85b5b;
font-size: .9rem;
}
// Clear floats
.mktoClear {
clear: both;
}
}
//////////////////////////////// MEDIA QUERIES /////////////////////////////////
@include media(small) {
#tc-downloads {
.mktoForm {
grid-template-columns: 1fr;
}
.mktoFormRow:has(.mktoEmailField),
.mktoFormRow:has(.mktoCheckboxList),
.mktoButtonRow {
grid-column: auto;
}
}
}

View File

@ -41,7 +41,9 @@ The following heartbeat plugin configuration options are available:
- **url**: _({{% req %}})_ URL of heartbeat endpoint.
- **instance_id**: _({{% req %}})_ Unique identifier for the Telegraf instance
or agent (also known as the agent ID).
- **token**: Authorization token for the heartbeat endpoint
- **token**: _({{% req text="Required with auth enabled" %}})_
{{% product-name %}} API token for the heartbeat endpoint.
The token must have **write** permissions on the **Heartbeat** API.
- **interval**: Interval for sending heartbeat messages. Default is `1m` (every minute).
- **include**: Information to include in the heartbeat message.
Available options are:
@ -56,12 +58,14 @@ The following heartbeat plugin configuration options are available:
### Example heartbeat output plugin
The following is an example heartbeat output plugin configuration that uses
an `agent_id` [configuration parameter](#) to specify the `instance_id`.
an `agent_id` [configuration parameter](/telegraf/controller/configs/dynamic-values/#parameters)
to specify the `instance_id`.
```toml
```toml { .tc-dynamic-values }
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "&{agent_id}"
token = "${INFLUX_TOKEN}"
interval = "1m"
include = ["hostname", "statistics", "configs"]
@ -69,6 +73,17 @@ an `agent_id` [configuration parameter](#) to specify the `instance_id`.
User-Agent = "telegraf"
```
> [!Important]
> #### Authorize heartbeats using an API token
>
> If {{% product-name %}} requires authorization on the **Heartbeat** API,
> include the `token` option in your heartbeat plugin configuration.
> Provide a {{% product-name %}} token with **write** permissions on the
> **Heartbeat** API.
>
> We recommend defining the `INFLUX_TOKEN` environment variable when starting
> Telegraf and using that to define the token in your heartbeat plugin.
## Verify a new agent
1. Open {{% product-name %}} and go to **Agents**.

View File

@ -1,24 +1,135 @@
---
title: Set agent statuses
description: >
Understand how {{% product-name %}} receives and displays agent statuses from
the heartbeat output plugin.
Configure agent status evaluation using CEL expressions in the Telegraf
heartbeat output plugin and view statuses in {{% product-name %}}.
menu:
telegraf_controller:
name: Set agent statuses
parent: Manage agents
weight: 104
related:
- /telegraf/controller/reference/agent-status-eval/, Agent status evaluation reference
- /telegraf/controller/agents/reporting-rules/
- /telegraf/v1/output-plugins/heartbeat/, Heartbeat output plugin
---
Agent statuses come from the Telegraf heartbeat output plugin and are sent with
each heartbeat request.
The plugin reports an `ok` status.
Agent statuses reflect the health of a Telegraf instance based on runtime data.
The Telegraf [heartbeat output plugin](/telegraf/v1/output-plugins/heartbeat/)
evaluates [Common Expression Language (CEL)](/telegraf/controller/reference/agent-status-eval/)
expressions against agent metrics, error counts, and plugin statistics to
determine the status sent with each heartbeat.
<!-- TODO: Update version to 1.38.2 after it's released -->
> [!Note]
> A future Telegraf release will let you configure logic that sets the status value.
{{% product-name %}} also applies reporting rules to detect stale agents.
If an agent does not send a heartbeat within the rule's threshold, Controller
marks the agent as **Not Reporting** until it resumes sending heartbeats.
> #### Requires Telegraf v1.38.0+
>
> Agent status evaluation in the Heartbeat output plugins requires Telegraf
> v1.38.0+.
> [!Warning]
> #### Heartbeat output plugin panic in Telegraf v1.38.0
>
> Telegraf v1.38.0 introduced a panic in the Heartbeat output plugin that
> prevents Telegraf from starting when the plugin is enabled. Telegraf v1.38.2
> will include a fix, but in the meantime, to use the Heartbeat output plugin,
> do one of the following:
>
> - Revert back to Telegraf v1.37.x _(Recommended)_
> - Use a Telegraf nightly build
> - Build Telegraf from source
## Status values
{{% product-name %}} displays the following agent statuses:
| Status | Source | Description |
| :---------------- | :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Ok** | Heartbeat plugin | The agent is healthy. Set when the `ok` CEL expression evaluates to `true`. |
| **Warn** | Heartbeat plugin | The agent has a potential issue. Set when the `warn` CEL expression evaluates to `true`. |
| **Fail** | Heartbeat plugin | The agent has a critical problem. Set when the `fail` CEL expression evaluates to `true`. |
| **Undefined** | Heartbeat plugin | No expression matched and the `default` is set to `undefined`, or the `initial` status is `undefined`. |
| **Not Reporting** | {{% product-name %}} | The agent has not sent a heartbeat within the [reporting rule](/telegraf/controller/agents/reporting-rules/) threshold. {{% product-name %}} applies this status automatically. |
## How status evaluation works
You define CEL expressions for `ok`, `warn`, and `fail` in the
`[outputs.heartbeat.status]` section of your heartbeat plugin configuration.
Telegraf evaluates expressions in a configurable order and assigns the status
of the first expression that evaluates to `true`.
For full details on evaluation flow, configuration options, and available
variables and functions, see the
[Agent status evaluation reference](/telegraf/controller/reference/agent-status-eval/).
## Configure agent statuses
To configure status evaluation, add `"status"` to the `include` list in your
heartbeat plugin configuration and define CEL expressions in the
`[outputs.heartbeat.status]` section.
### Example: Basic health check
Report `ok` when metrics are flowing.
If no metrics arrive, fall back to the `fail` status.
```toml { .tc-dynamic-values }
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "&{agent_id}"
token = "${INFLUX_TOKEN}"
interval = "1m"
include = ["hostname", "statistics", "configs", "logs", "status"]
[outputs.heartbeat.status]
ok = "metrics > 0"
default = "fail"
```
### Example: Error-based status
Warn when errors are logged, fail when the error count is high.
```toml { .tc-dynamic-values }
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "&{agent_id}"
token = "${INFLUX_TOKEN}"
interval = "1m"
include = ["hostname", "statistics", "configs", "logs", "status"]
[outputs.heartbeat.status]
ok = "log_errors == 0 && log_warnings == 0"
warn = "log_errors > 0"
fail = "log_errors > 10"
order = ["fail", "warn", "ok"]
default = "ok"
```
### Example: Composite condition
Combine error count and buffer pressure signals.
```toml { .tc-dynamic-values }
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "&{agent_id}"
token = "${INFLUX_TOKEN}"
interval = "1m"
include = ["hostname", "statistics", "configs", "logs", "status"]
[outputs.heartbeat.status]
ok = "metrics > 0 && log_errors == 0"
warn = "log_errors > 0 || (has(outputs.influxdb_v2) && outputs.influxdb_v2.exists(o, o.buffer_fullness > 0.8))"
fail = "log_errors > 5 && has(outputs.influxdb_v2) && outputs.influxdb_v2.exists(o, o.buffer_fullness > 0.9)"
order = ["fail", "warn", "ok"]
default = "ok"
```
For more examples including buffer health, plugin-specific checks, and
time-based expressions, see
[CEL expression examples](/telegraf/controller/reference/agent-status-eval/examples/).
## View an agent's status

View File

@ -65,17 +65,29 @@ configuration with a [Telegraf heartbeat output plugin](/telegraf/v1/output-plug
This plugin reports agent information back to the {{% product-name %}} heartbeat
API and lets you monitor the health of your deployed Telegraf agents.
```toml
```toml { .tc-dynamic-values }
[[outputs.heartbeat]]
url = "http://localhost:8000/agents/heartbeat"
instance_id = "&{agent_id}"
interval = "1m"
include = ["hostname", "statistics", "configs"]
token = "${INFLUX_TOKEN}"
```
To monitor agents with {{% product-name %}}, include a heartbeat plugin in
your Telegraf configurations.
> [!Important]
> #### Authorize heartbeats using an API token
>
> If {{% product-name %}} requires authorization on the **Heartbeat** API,
> include the `token` option in your heartbeat plugin configuration.
> Provide a {{% product-name %}} token with **write** permissions on the
> **Heartbeat** API.
>
> We recommend defining the `INFLUX_TOKEN` environment variable when starting
> Telegraf and using that to define the token in your heartbeat plugin.
## Next steps
- Use [dynamic values](/telegraf/controller/configs/dynamic-values/)

View File

@ -46,8 +46,7 @@ requesting the configuration from {{% product-name %}}.
### Use parameters in Telegraf configurations
{{% telegraf/dynamic-values %}}
```toml
```toml { .tc-dynamic-values }
[[outputs.influxdb_v2]]
# Parameter with a default value
urls = ["&{db_host:https://localhost:8181}"]
@ -56,7 +55,6 @@ requesting the configuration from {{% product-name %}}.
# Required parameter without a default value
instance_id = "&{agent_id}"
```
{{% /telegraf/dynamic-values %}}
The example above uses two parameters:
@ -117,15 +115,13 @@ For more information about Telegraf environment variable syntax, see
### Use environment variables in Telegraf configurations
{{% telegraf/dynamic-values %}}
```toml
```toml { .tc-dynamic-values }
[[inputs.http]]
urls = ["${API_ENDPOINT:-http://localhost:8080}/metrics"]
[inputs.http.headers]
Authorization = "Bearer ${AUTH_TOKEN}"
```
{{% /telegraf/dynamic-values %}}
The example above uses two environment variables:
@ -150,8 +146,7 @@ telegraf \
Use secrets for credentials or tokens you do not want to store in plain text.
Secrets require a secret store and its corresponding `secretstores` plugin.
{{% telegraf/dynamic-values %}}
```toml
```toml { .tc-dynamic-values }
# Configure a secret store plugin
[[secretstores.vault]]
id = "my_vault"
@ -164,7 +159,6 @@ Secrets require a secret store and its corresponding `secretstores` plugin.
host = "my_influxdb.com:8181"
token = "@{my_vault:influx_token}"
```
{{% /telegraf/dynamic-values %}}
For more information about Telegraf secrets and secret stores, see
[Telegraf configuration options—Secret stores](/telegraf/v1/configuration/#secret-stores).

View File

@ -40,6 +40,24 @@ telegraf \
Telegraf retrieves and validates the configuration from {{% product-name %}}
and then starts the `telegraf` process using the loaded configuration.
### Retrieve a configuration with authorization enabled
If {{% product-name %}} is configured to require authentication on the **Configs**
API, define the `INFLUX_TOKEN` environment variable to authorize Telegraf
to retrieve a configuration:
<!--pytest.mark.skip-->
```bash { placeholders="YOUR_TC_API_TOKEN" }
export INFLUX_TOKEN=YOUR_TC_API_TOKEN
telegraf \
--config "http://telegraf_controller.example.com/api/configs/xxxxxx/toml
```
Replace {{% code-placeholder-key %}}`YOUR_TC_API_TOKEN`{{% /code-placeholder-key %}}
with your {{% product-name %}} API token. This token must have **read**
permissions on the **Configs** API.
## Set dynamic values
Telegraf and {{% product-name %}} let you
@ -58,13 +76,11 @@ values—for example:
##### Configuration TOML with a parameter
{{% telegraf/dynamic-values %}}
```toml
```toml { .tc-dynamic-values }
[[outputs.heartbeat]]
instance_id = "&{agent_id}"
# ...
```
{{% /telegraf/dynamic-values %}}
##### Set the parameter value in the configuration URL
@ -88,15 +104,13 @@ starting Telegraf—for example:
##### Configuration TOML with an environment variable
{{% telegraf/dynamic-values %}}
```toml
```toml { .tc-dynamic-values }
[[inputs.http]]
urls = ["http://localhost:8080/metrics"]
[inputs.http.headers]
Authorization = "Bearer ${AUTH_TOKEN}"
```
{{% /telegraf/dynamic-values %}}
##### Set the environment variable before starting Telegraf
@ -135,21 +149,50 @@ parameters, environment variables, auto-update functionality, and Telegraf
{{< img-hd src="/img/telegraf/controller-command-builder.png" alt="Build Telegraf commands with Telegraf Controller" />}}
4. Define dynamic values and select options for your command:
4. _Optional_: To download a configuration and run it from your local filesystem
rather than having Telegraf retrieve it directly from {{% product-name %}},
enable the **Use local configuration file** option.
See more information [below](#download-a-configuration-to-your-local-filesystem).
5. Define dynamic values and select options for your command:
- Set environment variable values
- Set parameter values
- Enable automatic configuration updates and specify the check interval
- Add label selectors to run certain plugins based on configuration labels
5. Click **Copy Commands** to copy the contents of the codeblock to your clipboard.
6. Click **Copy Commands** to copy the contents of the codeblock to your clipboard.
The tool provides commands for Linux, macOS, and Windows (PowerShell).
> [!Warning]
> #### Some browsers restrict copying to clipboard
>
> Your browser may not allow the **Copy Commands** button to copy to your
> clipboard under the following conditions:
>
> - You're using an IP or domain name other than `0.0.0.0` or `localhost` and
> - You're using HTTP, not HTTPS
<!-- TODO: Provide information about downloading configs when the functionality is added -->
### Download a configuration to your local filesystem
With the **Use local configuration file** option enabled in the command builder,
{{% product-name %}} lets you configure the directory path and file name to use
for the configuration.
1. Define dynamic values and select options for your command:
- Set file details
- Set environment variable values
- Set parameter values
- Enable automatic configuration updates and specify the check strategy
- Add label selectors to run certain plugins based on configuration labels
2. Click **Download Config** to download the configuration to your local machine.
The downloaded TOML files uses the file name specified in the
**File Details** tab and includes all the specified parameter replacements.
3. Click **Copy Commands** to copy the contents of the codeblock to your clipboard.
The tool provides commands for Linux, macOS, and Windows (PowerShell).
See [information about copying to your clipboard](#some-browsers-restrict-copying-to-clipboard).
{{< img-hd src="/img/telegraf/controller-command-builder-dl.png" alt="Telegraf Controller command builder" />}}

View File

@ -18,6 +18,7 @@ configurations, monitoring agents, and organizing plugins.
- [Download and install {{% product-name %}}](#download-and-install-telegraf-controller)
- [Set up your database](#set-up-your-database)
- [Configure {{% product-name %}}](#configure-telegraf-controller)
- [Set up the owner account](#set-up-the-owner-account)
- [Access {{% product-name %}}](#access-telegraf-controller)
## System Requirements
@ -75,15 +76,7 @@ $env:TELEGRAF_CONTROLLER_EULA="accept"
1. **Download the {{% product-name %}} executable.**
> [!Note]
> #### Contact InfluxData for download
>
> If you are currently participating in the {{% product-name %}} private alpha,
> send your operating system and architecture to InfluxData and we will
> provide you with the appropriate {{% product-name %}} executable.
>
> If you are not currently in the private alpha and would like to be,
> [request early access](https://www.influxdata.com/products/telegraf-enterprise).
{{< telegraf/tc-downloads >}}
2. **Install {{% product-name %}}**.
@ -508,6 +501,93 @@ $env:TELEGRAF_CONTROLLER_EULA=accept
{{% /tab-content %}}
{{< /tabs-wrapper >}}
## Set up the owner account
The first time you access {{% product-name %}}, you need to create an owner account.
The owner has full administrative access to the application, including the
ability to manage users, configurations, and agents.
You can create the owner account using one of four methods:
- [Interactive CLI setup](#interactive-cli-setup) when starting the application
- [Environment variables](#environment-variable-setup) set before starting the application
- [Command line flags](#command-line-flag-setup) passed when starting the application
- [Web interface setup](#web-interface-setup) after starting the application
### Interactive CLI setup
When you start {{% product-name %}} in interactive mode (default) and no owner
account exists, {{% product-name %}} prompts you to provide owner username,
email address, and password.
### Environment variable setup
You can configure the owner account by setting environment variables before
starting {{% product-name %}}.
This method is useful for automated deployments and containerized environments.
| Environment variable | Description |
| :------------------- | :------------------ |
| `OWNER_EMAIL` | Owner email address |
| `OWNER_USERNAME` | Owner username |
| `OWNER_PASSWORD` | Owner password |
Set all three environment variables and then start the application:
```bash
export OWNER_EMAIL="admin@example.com"
export OWNER_USERNAME="admin"
export OWNER_PASSWORD="secure-password-here"
./telegraf-controller
```
> [!Note]
> If an owner account already exists, {{% product-name %}} ignores these
> environment variables.
> [!Important]
> If an administrator account already exists with the specified username,
> that account is promoted to owner.
### Command line flag setup
You can also pass owner account details as command line flags when starting
{{% product-name %}}.
| Flag | Description |
|:-------------------------|:-----------------------|
| `--owner-email=EMAIL` | Owner email address |
| `--owner-username=NAME` | Owner username |
| `--owner-password=PASS` | Owner password |
Pass all three flags when starting the application:
```bash
./telegraf-controller \
--owner-email="admin@example.com" \
--owner-username="admin" \
--owner-password="secure-password-here"
```
> [!Tip]
> Command line flags take precedence over environment variables.
> If you set both, {{% product-name %}} uses the values from the command line flags.
### Web interface setup
If no owner account exists when you start {{% product-name %}} in non-interactive
mode, the web interface displays a setup page where you can create one.
1. Navigate to the [{{% product-name %}} URL](#access-telegraf-controller) in your browser.
2. Fill in the **Username**, **Email**, and **Password** fields.
3. Click **Create Account**.
{{< img-hd src="/img/telegraf/controller-setup-owner-account.png" alt="Owner account setup page" />}}
For more information about user roles and permissions, see
[Authorization](/telegraf/controller/reference/authorization/).
## Access {{% product-name %}}
Once started, access the {{% product-name %}} web interface at

View File

@ -0,0 +1,97 @@
---
title: Agent status evaluation
description: >
Reference documentation for Common Expression Language (CEL) expressions used
to evaluate Telegraf agent status.
menu:
telegraf_controller:
name: Agent status evaluation
parent: Reference
weight: 107
related:
- /telegraf/controller/agents/status/
- /telegraf/v1/output-plugins/heartbeat/
---
The Telegraf [heartbeat output plugin](/telegraf/v1/output-plugins/heartbeat/)
uses CEL expressions to evaluate agent status based on runtime data such as
metric counts, error rates, and plugin statistics.
[CEL (Common Expression Language)](https://cel.dev) is a lightweight expression
language designed for evaluating simple conditions.
## How status evaluation works
You define CEL expressions for three status levels in the
`[outputs.heartbeat.status]` section of your Telegraf configuration:
- **ok** — The agent is healthy.
- **warn** — The agent has a potential issue.
- **fail** — The agent has a critical problem.
Each expression is a CEL program that returns a boolean value.
Telegraf evaluates expressions in a configurable order (default:
`ok`, `warn`, `fail`) and assigns the status of the **first expression that
evaluates to `true`**.
If no expression evaluates to `true`, the `default` status is used
(default: `"ok"`).
### Initial status
Use the `initial` setting to define a status before the first Telegraf flush
cycle.
If `initial` is not set or is empty, Telegraf evaluates the status expressions
immediately, even before the first flush.
### Evaluation order
The `order` setting controls which expressions are evaluated and in what
sequence.
> [!Note]
> If you omit a status from the `order` list, its expression is **not
> evaluated**.
## Configuration reference
Configure status evaluation in the `[outputs.heartbeat.status]` section of the
heartbeat output plugin.
You must include `"status"` in the `include` list for status evaluation to take
effect.
```toml
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "agent-123"
interval = "1m"
include = ["hostname", "statistics", "status"]
[outputs.heartbeat.status]
## CEL expressions that return a boolean.
## The first expression that evaluates to true sets the status.
ok = "metrics > 0"
warn = "log_errors > 0"
fail = "log_errors > 10"
## Evaluation order (default: ["ok", "warn", "fail"])
order = ["ok", "warn", "fail"]
## Default status when no expression matches
## Options: "ok", "warn", "fail", "undefined"
default = "ok"
## Initial status before the first flush cycle
## Options: "ok", "warn", "fail", "undefined", ""
# initial = ""
```
| Option | Type | Default | Description |
|:-------|:-----|:--------|:------------|
| `ok` | string (CEL) | `"false"` | Expression that, when `true`, sets status to **ok**. |
| `warn` | string (CEL) | `"false"` | Expression that, when `true`, sets status to **warn**. |
| `fail` | string (CEL) | `"false"` | Expression that, when `true`, sets status to **fail**. |
| `order` | list of strings | `["ok", "warn", "fail"]` | Order in which expressions are evaluated. |
| `default` | string | `"ok"` | Status used when no expression evaluates to `true`. Options: `ok`, `warn`, `fail`, `undefined`. |
| `initial` | string | `""` | Status before the first flush. Options: `ok`, `warn`, `fail`, `undefined`, `""` (empty = evaluate expressions). |
{{< children hlevel="h2" >}}

View File

@ -0,0 +1,257 @@
---
title: CEL expression examples
description: >
Real-world examples of CEL expressions for evaluating Telegraf agent status.
menu:
telegraf_controller:
name: Examples
parent: Agent status evaluation
weight: 203
related:
- /telegraf/controller/agents/status/
- /telegraf/controller/reference/agent-status-eval/variables/
- /telegraf/controller/reference/agent-status-eval/functions/
---
Each example includes a scenario description, the CEL expression, a full
heartbeat plugin configuration block, and an explanation.
For the full list of available variables and functions, see:
- [CEL variables](/telegraf/controller/reference/agent-status-eval/variables/)
- [CEL functions and operators](/telegraf/controller/reference/agent-status-eval/functions/)
## Basic health check
**Scenario:** Report `ok` when Telegraf is actively processing metrics.
Fall back to the default status (`ok`) when no expression matches — this means
the agent is healthy as long as metrics are flowing.
**Expression:**
```js
ok = "metrics > 0"
```
**Configuration:**
```toml
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "agent-123"
interval = "1m"
include = ["hostname", "statistics", "configs", "logs", "status"]
[outputs.heartbeat.status]
ok = "metrics > 0"
default = "fail"
```
**How it works:** If the heartbeat plugin received metrics since the last
heartbeat, the status is `ok`.
If no metrics arrived, no expression matches and the `default` status of `fail`
is used, indicating the agent is not processing data.
## Error rate monitoring
**Scenario:** Warn when any errors are logged and fail when the error count is
high.
**Expressions:**
```js
warn = "log_errors > 0"
fail = "log_errors > 10"
```
**Configuration:**
```toml
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "agent-123"
interval = "1m"
include = ["hostname", "statistics", "configs", "logs", "status"]
[outputs.heartbeat.status]
ok = "log_errors == 0 && log_warnings == 0"
warn = "log_errors > 0"
fail = "log_errors > 10"
order = ["fail", "warn", "ok"]
default = "ok"
```
**How it works:** Expressions are evaluated in `fail`, `warn`, `ok` order.
If more than 10 errors occurred since the last heartbeat, the status is `fail`.
If 1-10 errors occurred, the status is `warn`.
If no errors or warnings occurred, the status is `ok`.
## Buffer health
**Scenario:** Warn when any output plugin's buffer exceeds 80% fullness,
indicating potential data backpressure.
**Expression:**
```js
warn = "outputs.influxdb_v2.exists(o, o.buffer_fullness > 0.8)"
fail = "outputs.influxdb_v2.exists(o, o.buffer_fullness > 0.95)"
```
**Configuration:**
```toml
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "agent-123"
interval = "1m"
include = ["hostname", "statistics", "configs", "logs", "status"]
[outputs.heartbeat.status]
ok = "metrics > 0"
warn = "outputs.influxdb_v2.exists(o, o.buffer_fullness > 0.8)"
fail = "outputs.influxdb_v2.exists(o, o.buffer_fullness > 0.95)"
order = ["fail", "warn", "ok"]
default = "ok"
```
**How it works:** The `outputs.influxdb_v2` map contains a list of all
`influxdb_v2` output plugin instances.
The `exists()` function iterates over all instances and returns `true` if any
instance's `buffer_fullness` exceeds the threshold.
At 95% fullness, the status is `fail`; at 80%, `warn`; otherwise `ok`.
## Plugin-specific checks
**Scenario:** Monitor a specific input plugin for collection errors and use
safe access patterns to avoid errors when the plugin is not configured.
**Expression:**
```js
warn = "has(inputs.cpu) && inputs.cpu.exists(i, i.errors > 0)"
fail = "has(inputs.cpu) && inputs.cpu.exists(i, i.startup_errors > 0)"
```
**Configuration:**
```toml
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "agent-123"
interval = "1m"
include = ["hostname", "statistics", "configs", "logs", "status"]
[outputs.heartbeat.status]
ok = "metrics > 0"
warn = "has(inputs.cpu) && inputs.cpu.exists(i, i.errors > 0)"
fail = "has(inputs.cpu) && inputs.cpu.exists(i, i.startup_errors > 0)"
order = ["fail", "warn", "ok"]
default = "ok"
```
**How it works:** The `has()` function checks if the `cpu` key exists in the
`inputs` map before attempting to access it.
This prevents evaluation errors when the plugin is not configured.
If the plugin has startup errors, the status is `fail`.
If it has collection errors, the status is `warn`.
## Composite conditions
**Scenario:** Combine multiple signals to detect a degraded agent — high error
count combined with output buffer pressure.
**Expression:**
```js
fail = "log_errors > 5 && has(outputs.influxdb_v2) && outputs.influxdb_v2.exists(o, o.buffer_fullness > 0.9)"
```
**Configuration:**
```toml
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "agent-123"
interval = "1m"
include = ["hostname", "statistics", "configs", "logs", "status"]
[outputs.heartbeat.status]
ok = "metrics > 0 && log_errors == 0"
warn = "log_errors > 0 || (has(outputs.influxdb_v2) && outputs.influxdb_v2.exists(o, o.buffer_fullness > 0.8))"
fail = "log_errors > 5 && has(outputs.influxdb_v2) && outputs.influxdb_v2.exists(o, o.buffer_fullness > 0.9)"
order = ["fail", "warn", "ok"]
default = "ok"
```
**How it works:** The `fail` expression requires **both** a high error count
**and** buffer pressure to trigger.
The `warn` expression uses `||` to trigger on **either** condition independently.
This layered approach avoids false alarms from transient spikes in a single
metric.
## Time-based expressions
**Scenario:** Warn when the time since the last successful heartbeat exceeds a
threshold, indicating potential connectivity or performance issues.
**Expression:**
```js
warn = "now() - last_update > duration('10m')"
fail = "now() - last_update > duration('30m')"
```
**Configuration:**
```toml
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "agent-123"
interval = "1m"
include = ["hostname", "statistics", "configs", "logs", "status"]
[outputs.heartbeat.status]
ok = "metrics > 0"
warn = "now() - last_update > duration('10m')"
fail = "now() - last_update > duration('30m')"
order = ["fail", "warn", "ok"]
default = "undefined"
initial = "undefined"
```
**How it works:** The `now()` function returns the current time and
`last_update` is the timestamp of the last successful heartbeat.
Subtracting them produces a duration that can be compared against a threshold.
The `initial` status is set to `undefined` so new agents don't immediately show
a stale-data warning before their first successful heartbeat.
## Custom evaluation order
**Scenario:** Use fail-first evaluation to prioritize detecting critical issues
before checking for healthy status.
**Configuration:**
```toml
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "agent-123"
interval = "1m"
include = ["hostname", "statistics", "configs", "logs", "status"]
[outputs.heartbeat.status]
ok = "metrics > 0 && log_errors == 0"
warn = "log_errors > 0"
fail = "log_errors > 10 || agent.metrics_dropped > 100"
order = ["fail", "warn", "ok"]
default = "undefined"
```
**How it works:** By setting `order = ["fail", "warn", "ok"]`, the most severe
conditions are checked first.
If the agent has more than 10 logged errors or has dropped more than 100
metrics, the status is `fail` — regardless of whether the `ok` or `warn`
expression would also match.
This is the recommended order for production deployments where early detection
of critical issues is important.

View File

@ -0,0 +1,120 @@
---
title: CEL functions and operators
description: >
Reference for functions and operators available in CEL expressions used to
evaluate Telegraf agent status.
menu:
telegraf_controller:
name: Functions
parent: Agent status evaluation
weight: 202
---
CEL expressions for agent status evaluation support built-in CEL operators and
the following function libraries.
## Time functions
### `now()`
Returns the current time.
Use with `last_update` to calculate durations or detect stale data.
```js
// True if more than 10 minutes since last heartbeat
now() - last_update > duration('10m')
```
```js
// True if more than 5 minutes since last heartbeat
now() - last_update > duration('5m')
```
## Math functions
Math functions from the
[CEL math library](https://github.com/google/cel-go/blob/master/ext/README.md#math)
are available for numeric calculations.
### Commonly used functions
| Function | Description | Example |
|:---------|:------------|:--------|
| `math.greatest(a, b, ...)` | Returns the greatest value. | `math.greatest(log_errors, log_warnings)` |
| `math.least(a, b, ...)` | Returns the least value. | `math.least(agent.metrics_gathered, 1000)` |
### Example
```js
// Warn if either errors or warnings exceed a threshold
math.greatest(log_errors, log_warnings) > 5
```
## String functions
String functions from the
[CEL strings library](https://github.com/google/cel-go/blob/master/ext/README.md#strings)
are available for string operations.
These are useful when checking plugin `alias` or `id` fields.
### Example
```js
// Check if any input plugin has an alias containing "critical"
inputs.cpu.exists(i, has(i.alias) && i.alias.contains("critical"))
```
## Encoding functions
Encoding functions from the
[CEL encoder library](https://github.com/google/cel-go/blob/master/ext/README.md#encoders)
are available for encoding and decoding values.
## Operators
CEL supports standard operators for building expressions.
### Comparison operators
| Operator | Description | Example |
|:---------|:------------|:--------|
| `==` | Equal | `metrics == 0` |
| `!=` | Not equal | `log_errors != 0` |
| `<` | Less than | `agent.metrics_gathered < 100` |
| `<=` | Less than or equal | `buffer_fullness <= 0.5` |
| `>` | Greater than | `log_errors > 10` |
| `>=` | Greater than or equal | `metrics >= 1000` |
### Logical operators
| Operator | Description | Example |
|:---------|:------------|:--------|
| `&&` | Logical AND | `log_errors > 0 && metrics == 0` |
| `\|\|` | Logical OR | `log_errors > 10 \|\| log_warnings > 50` |
| `!` | Logical NOT | `!(metrics > 0)` |
### Arithmetic operators
| Operator | Description | Example |
|:---------|:------------|:--------|
| `+` | Addition | `log_errors + log_warnings` |
| `-` | Subtraction | `agent.metrics_gathered - agent.metrics_dropped` |
| `*` | Multiplication | `log_errors * 2` |
| `/` | Division | `agent.metrics_dropped / agent.metrics_gathered` |
| `%` | Modulo | `metrics % 100` |
### Ternary operator
```js
// Conditional expression
log_errors > 10 ? true : false
```
### List operations
| Function | Description | Example |
|:---------|:------------|:--------|
| `exists(var, condition)` | True if any element matches. | `inputs.cpu.exists(i, i.errors > 0)` |
| `all(var, condition)` | True if all elements match. | `outputs.influxdb_v2.all(o, o.errors == 0)` |
| `size()` | Number of elements. | `inputs.cpu.size() > 0` |
| `has()` | True if a field or key exists. | `has(inputs.cpu)` |

View File

@ -0,0 +1,150 @@
---
title: CEL variables
description: >
Reference for variables available in CEL expressions used to evaluate
Telegraf agent status in {{% product-name %}}.
menu:
telegraf_controller:
name: Variables
parent: Agent status evaluation
weight: 201
---
CEL expressions for agent status evaluation have access to variables that
represent data collected by Telegraf since the last successful heartbeat message
(unless noted otherwise).
## Top-level variables
| Variable | Type | Description |
| :------------- | :--- | :---------------------------------------------------------------------------------------------------- |
| `metrics` | int | Number of metrics arriving at the heartbeat output plugin. |
| `log_errors` | int | Number of errors logged by the Telegraf instance. |
| `log_warnings` | int | Number of warnings logged by the Telegraf instance. |
| `last_update` | time | Timestamp of the last successful heartbeat message. Use with `now()` to calculate durations or rates. |
| `agent` | map | Agent-level statistics. See [Agent statistics](#agent-statistics). |
| `inputs` | map | Input plugin statistics. See [Input plugin statistics](#input-plugin-statistics-inputs). |
| `outputs` | map | Output plugin statistics. See [Output plugin statistics](#output-plugin-statistics-outputs). |
## Agent statistics
The `agent` variable is a map containing aggregate statistics for the entire
Telegraf instance.
These fields correspond to the `internal_agent` metric from the
Telegraf [internal input plugin](/telegraf/v1/plugins/#input-internal).
| Field | Type | Description |
| :----------------------- | :--- | :-------------------------------------------------- |
| `agent.metrics_written` | int | Total metrics written by all output plugins. |
| `agent.metrics_rejected` | int | Total metrics rejected by all output plugins. |
| `agent.metrics_dropped` | int | Total metrics dropped by all output plugins. |
| `agent.metrics_gathered` | int | Total metrics collected by all input plugins. |
| `agent.gather_errors` | int | Total collection errors across all input plugins. |
| `agent.gather_timeouts` | int | Total collection timeouts across all input plugins. |
### Example
```js
agent.gather_errors > 0
```
## Input plugin statistics (`inputs`)
The `inputs` variable is a map where each key is a plugin type (for example,
`cpu` for `inputs.cpu`) and the value is a **list** of plugin instances.
Each entry in the list represents one configured instance of that plugin type.
These fields correspond to the `internal_gather` metric from the Telegraf
[internal input plugin](/telegraf/v1/plugins/#input-internal).
| Field | Type | Description |
| :----------------- | :----- | :---------------------------------------------------------------------------------------- |
| `id` | string | Unique plugin identifier. |
| `alias` | string | Alias set for the plugin. Only exists if an alias is defined in the plugin configuration. |
| `errors` | int | Collection errors for this plugin instance. |
| `metrics_gathered` | int | Number of metrics collected by this instance. |
| `gather_time_ns` | int | Time spent gathering metrics, in nanoseconds. |
| `gather_timeouts` | int | Number of timeouts during metric collection. |
| `startup_errors` | int | Number of times the plugin failed to start. |
### Access patterns
Access a specific plugin type and iterate over its instances:
```js
// Check if any cpu input instance has errors
inputs.cpu.exists(i, i.errors > 0)
```
```js
// Access the first instance of the cpu input
inputs.cpu[0].metrics_gathered
```
Use `has()` to safely check if a plugin type exists before accessing it:
```js
// Safe access — returns false if no cpu input is configured
has(inputs.cpu) && inputs.cpu.exists(i, i.errors > 0)
```
## Output plugin statistics (`outputs`)
The `outputs` variable is a map with the same structure as `inputs`.
Each key is a plugin type (for example, `influxdb_v3` for `outputs.influxdb_v3`)
and the value is a list of plugin instances.
These fields correspond to the `internal_write` metric from the Telegraf
[internal input plugin](/telegraf/v1/plugins/#input-internal).
| Field | Type | Description |
| :----------------- | :----- | :------------------------------------------------------------------------------------------------------- |
| `id` | string | Unique plugin identifier. |
| `alias` | string | Alias set for the plugin. Only exists if an alias is defined in the plugin configuration. |
| `errors` | int | Write errors for this plugin instance. |
| `metrics_filtered` | int | Number of metrics filtered by the output. |
| `write_time_ns` | int | Time spent writing metrics, in nanoseconds. |
| `startup_errors` | int | Number of times the plugin failed to start. |
| `metrics_added` | int | Number of metrics added to the output buffer. |
| `metrics_written` | int | Number of metrics written to the output destination. |
| `metrics_rejected` | int | Number of metrics rejected by the service or serialization. |
| `metrics_dropped` | int | Number of metrics dropped (for example, due to buffer fullness). |
| `buffer_size` | int | Current number of metrics in the output buffer. |
| `buffer_limit` | int | Capacity of the output buffer. Irrelevant for disk-based buffers. |
| `buffer_fullness` | float | Ratio of metrics in the buffer to capacity. Can exceed `1.0` (greater than 100%) for disk-based buffers. |
### Access patterns
```js
// Access the first instance of the InfluxDB v3 output plugin
outputs.influxdb_v3[0].metrics_written
```
```js
// Check if any InfluxDB v3 output has write errors
outputs.influxdb_v3.exists(o, o.errors > 0)
```
```js
// Check buffer fullness across all instances of an output
outputs.influxdb_v3.exists(o, o.buffer_fullness > 0.8)
```
Use `has()` to safely check if a plugin type exists before accessing it:
```js
// Safe access — returns false if no cpu input is configured
has(outputs.influxdb_v3) && outputs.influxdb_v3.exists(o, o.errors > 0)
```
## Accumulation behavior
Unless noted otherwise, all variable values are **accumulated since the last
successful heartbeat message**.
Use the `last_update` variable with `now()` to calculate rates — for example:
```js
// True if the error rate exceeds 1 error per minute
log_errors > 0 && duration.getMinutes(now() - last_update) > 0
&& log_errors / duration.getMinutes(now() - last_update) > 1
```

View File

@ -0,0 +1,79 @@
---
title: Authorization
description: >
Understand how authentication and authorization work in Telegraf Controller,
including user roles, API tokens, and endpoint security.
menu:
telegraf_controller:
name: Authorization
parent: Reference
weight: 106
related:
- /telegraf/controller/users/
- /telegraf/controller/tokens/
- /telegraf/controller/settings/
---
{{% product-name %}} uses session-based authentication for the web UI and
token-based authentication for API and Telegraf agent requests.
Both mechanisms work together to control who can access the system and what
actions they can perform.
## User roles
{{% product-name %}} enforces a four-tier role hierarchy.
Each role inherits the permissions of the roles below it, and higher roles
unlock additional administrative capabilities.
| Role | Description |
| :-------------- | :------------------------------------------------------------------------------------------------------------------- |
| **Owner** | Full system access. Manages users, tokens, and settings. Only one owner exists at a time. Created during initial setup. |
| **Administrator** | Full system access. Same capabilities as the owner except cannot transfer ownership. |
| **Manager** | Manages configurations, agents, labels, and reporting rules. Manages own API tokens. Cannot manage users or settings. |
| **Viewer** | Read-only access to configurations, agents, labels, and reporting rules. Cannot manage tokens, users, or settings. |
Only one owner can exist at a time.
The owner account is created during initial setup and cannot be deleted.
If you need to change the owner, the current owner must transfer ownership to
another user.
> [!Tip]
> To change the owner of your {{% product-name %}} instance, see [Transfer ownership](/telegraf/controller/users/transfer-ownership/).
## API tokens
API tokens authenticate programmatic API requests and Telegraf agent connections
to {{% product-name %}}.
Each token is scoped to the user who created it.
The token's effective permissions are restricted to the creating user's role---a
token cannot exceed the permissions of its owner.
If a user's role changes to a role with less permissions, all of that user's
existing tokens are automatically updated with restricted permissions or revoked
to match the new role.
Tokens use the `tc-apiv1_` prefix, making them easy to identify in configuration
files and scripts.
> [!Important]
> A token value is shown only once at the time of creation.
> Store it in a secure location immediately---you cannot retrieve it later.
## Endpoint authentication
By default, {{% product-name %}} requires authentication for API endpoints.
Administrators can selectively require authentication for individual endpoint
groups:
- **Agents** --- agent management endpoints
- **Configs** --- configuration management endpoints
- **Labels** --- label management endpoints
- **Reporting rules** --- reporting rule management endpoints
- **Heartbeat** --- agent heartbeat endpoints
When authentication is enabled for an endpoint group, every request to that
group must include a valid API token or an active session.
> [!Note]
> To configure which endpoint groups require authentication, see
> [Manage settings](/telegraf/controller/settings/).

View File

@ -0,0 +1,217 @@
---
title: Telegraf Controller release notes
description: >
Important features, bug fixes, and changes in Telegraf Controller releases.
menu:
telegraf_controller:
name: Release notes
parent: Reference
weight: 101
---
## v0.0.5-beta {date="2026-03-26"}
<!-- Link only be on the latest version, update and move with new versions. -->
[Download Telegraf Controller v0.0.5-beta](/telegraf/controller/install/#download-and-install-telegraf-controller)
### Important changes
This release introduces user and account management, API token authentication,
and configurable authentication options.
By default, authentication is required to interact with all API endpoints.
If you have agents reading configurations from and reporting heartbeats
to {{% product-name %}}, they will begin to fail with authorization errors.
**To avoid agent authorization errors:**
1. Temporarily disable authentication on the **Heartbeat** and **Configs** APIs.
You can use either the `--disable-auth-endpoints` command flag or the
`DISABLED_AUTH_ENDPOINTS` environment variable when starting
{{% product-name %}}.
{{< code-tabs-wrapper >}}
{{% code-tabs %}}
[Command flags](#)
[Environment Variables](#)
{{% /code-tabs %}}
{{% code-tab-content %}}
<!--pytest.mark.skip-->
```bash
telegraf_controller --disable-auth-endpoints=configs,heartbeat
```
{{% /code-tab-content %}}
{{% code-tab-content %}}
<!--pytest.mark.skip-->
```bash
export DISABLED_AUTH_ENDPOINTS="configs,heartbeat"
telegraf_controller --disable-auth-endpoints=configs,heartbeat
```
{{% /code-tab-content %}}
{{< /code-tabs-wrapper >}}
2. [Create an API token](/telegraf/controller/tokens/create/) with read
permissions on the **Configs** API and write permissions on the
**Heartbeat** API.
3. Use the `INFLUX_TOKEN` environment variable to define the `token` option
in your heartbeat output plugin configuration:
```toml { .tc-dynamic-values }
[[outputs.heartbeat]]
# ...
token = "${INFLUX_TOKEN}"
```
4. Define the `INFLUX_TOKEN` environment variable in your Telegraf
environment:
<!--pytest.mark.skip-->
```bash {placeholders="YOUR_TELEGRAF_CONTROLLER_TOKEN"}
export INFLUX_TOKEN=YOUR_TELEGRAF_CONTROLLER_TOKEN
telegraf --config "https://localhost:8888/api/configs/..."
```
Replace {{% code-placeholder-key %}}`YOUR_TELEGRAF_CONTROLLER_TOKEN`{{% /code-placeholder-key %}}
with your {{% product-name %}} API token.
> [!Important]
> It's important to use the `INFLUX_TOKEN` environment variable.
> When present, Telegraf uses this specific variable to set the token used
> in the `Authorization` header when requesting the configuration.
5. Navigate to the **Settings** page in {{% product-name %}} and reenable
authentication on the Configs and Heartbeat APIs. Save your changes.
### Features
- Add user authentication and session management with login and setup pages.
- Add user management with invite system, password reset, and password
complexity validation.
- Add token management with create workflow and management pages.
- Add account management page with ownership transfer flow.
- Add settings page.
- Add application version retrieval and display.
- Enhance Heartbeat plugin with logs, status configurations, and agent
status checks.
- Add dynamic parsing component support for Exec and Google Cloud PubSub Push plugins.
- Add plugin support to the Telegraf Builder UI:
- Aerospike (`inputs.aerospike`)
- Alibaba Cloud Monitor Service (Aliyun) (`inputs.aliyuncms`)
- Amazon Elastic Container Service (`inputs.ecs`)
- AMD ROCm System Management Interface (SMI) (`inputs.amd_rocm_smi`)
- AMQP Consumer (`inputs.amqp_consumer`)
- Apache (`inputs.apache`)
- APC UPSD (`inputs.apcupsd`)
- Apache Aurora (`inputs.aurora`)
- Azure Queue Storage (`inputs.azure_storage_queue`)
- Bcache (`inputs.bcache`)
- Beanstalkd (`inputs.beanstalkd`)
- Beat (`inputs.beat`)
- BIND 9 Nameserver (`inputs.bind`)
- Bond (`inputs.bond`)
- Burrow (`inputs.burrow`)
- Ceph Storage (`inputs.ceph`)
- chrony (`inputs.chrony`)
- Cisco Model-Driven Telemetry (MDT) (`inputs.cisco_telemetry_mdt`)
- ClickHouse (`inputs.clickhouse`)
- Google Cloud PubSub Push (`inputs.cloud_pubsub_push`)
- Amazon CloudWatch Metric Streams (`inputs.cloudwatch_metric_streams`)
- Netfilter Conntrack (`inputs.conntrack`)
- Hashicorp Consul (`inputs.consul`)
- Hashicorp Consul Agent (`inputs.consul_agent`)
- Bosch Rexroth ctrlX Data Layer (`inputs.ctrlx_datalayer`)
- Mesosphere Distributed Cloud OS (`inputs.dcos`)
- Device Mapper Cache (`inputs.dmcache`)
- Data Plane Development Kit (DPDK) (`inputs.dpdk`)
- Elasticsearch (`inputs.elasticsearch`)
- Ethtool (`inputs.ethtool`)
- Exec (`inputs.exec`)
- Fibaro (`inputs.fibaro`)
- File (`inputs.file`)
- Filecount (`inputs.filecount`)
- File statistics (`inputs.filestat`)
- Fireboard (`inputs.fireboard`)
- AWS Data Firehose (`inputs.firehose`)
- Fluentd (`inputs.fluentd`)
- Fritzbox (`inputs.fritzbox`)
- GitHub (`inputs.github`)
- gNMI (gRPC Network Management Interface) (`inputs.gnmi`)
- Google Cloud Storage (`inputs.google_cloud_storage`)
- GrayLog (`inputs.graylog`)
- HAProxy (`inputs.haproxy`)
- HDDtemp (`inputs.hddtemp`)
- HTTP (`inputs.http`)
- HTTP Listener v2 (`inputs.http_listener_v2`)
- HueBridge (`inputs.huebridge`)
- Hugepages (`inputs.hugepages`)
- Icinga2 (`inputs.icinga2`)
- InfiniBand (`inputs.infiniband`)
- InfluxDB (`inputs.influxdb`)
- InfluxDB Listener (`inputs.influxdb_listener`)
- InfluxDB V2 Listener (`inputs.influxdb_v2_listener`)
- Intel Baseband Accelerator (`inputs.intel_baseband`)
- Intel® Dynamic Load Balancer (`inputs.intel_dlb`)
- Intel® Platform Monitoring Technology (`inputs.intel_pmt`)
### Bug fixes
- Fix default Heartbeat plugin configuration and environment variable exports.
---
## v0.0.4-alpha {date="2026-02-05"}
### Features
- Require InfluxData EULA acceptance before starting the server.
- Add plugin support to the Telegraf Builder UI and TOML parser:
- ActiveMQ (`inputs.activemq`)
- Vault (`secretstores.vault`)
- All parsers
- All serializers
- Add support for custom logs directory.
- Reduce binary size.
### Bug fixes
- Fix question mark position in deletion popup.
---
## v0.0.3-alpha {date="2026-01-14"}
### Features
- Add linux-arm64 binary support.
- Add build validation for missing plugins.
- Add local file handling for configurations.
---
## v0.0.2-alpha {date="2026-01-13"}
### Features
- Identify external configurations for Telegraf agents.
- Add SSL support for backend connections.
- Add health check status API endpoint.
- Add `Last-Modified` header to GET TOML API response and remove duplicate
protocol handling.
- Compile native Rust NAPI server for heartbeat service.
### Bug fixes
- Fix default parsing unit to use seconds.
- Fix command line string generation.
---
## v0.0.1-alpha {date="2026-01-01"}
_Initial alpha build of Telegraf Controller._

View File

@ -0,0 +1,143 @@
---
title: Manage settings
description: >
Configure authentication requirements, login security, and password
policies in Telegraf Controller.
menu:
telegraf_controller:
name: Manage settings
weight: 9
---
Owners and administrators can configure authentication, login security, and
password requirements for {{% product-name %}}.
Navigate to the **Settings** page from the left navigation menu to view and
modify these settings.
{{< img-hd src="/img/telegraf/controller-settings.png" alt="Telegraf Controller settings page" />}}
## Require authentication per endpoint
{{% product-name %}} organizes API endpoints into groups.
Authentication can be required or disabled for each group independently, giving
you fine-grained control over which resources require credentials.
| Endpoint group | Covers |
| :---------------- | :------------------------------ |
| `agents` | Agent monitoring and management |
| `configs` | Configuration management |
| `labels` | Label management |
| `reporting-rules` | Reporting rule management |
| `heartbeat` | Agent heartbeat requests |
When authentication is disabled for a group, anyone with network access can use
those endpoints without an API token.
When enabled, requests require valid authentication.
> [!Note]
> By default, authentication is required for all endpoints.
To toggle authentication for endpoint groups:
1. Navigate to the **Settings** page.
2. Toggle authentication on or off for each endpoint group.
3. Click **Save**.
> [!Warning]
> Disabling authentication for endpoints means anyone with network access to
> {{% product-name %}} can access those resources without credentials.
### Environment variable and CLI flag
You can configure disabled authentication endpoints at startup using the
`DISABLED_AUTH_ENDPOINTS` environment variable or the `--disable-auth-endpoints`
CLI flag.
The value is a comma-separated list of endpoint groups, or `"*"` to disable
authentication for all endpoints.
```bash
# Disable auth for agents and heartbeat only
export DISABLED_AUTH_ENDPOINTS="agents,heartbeat"
# Disable auth for all endpoints
export DISABLED_AUTH_ENDPOINTS="*"
```
Using the CLI flag:
```bash
# Disable auth for agents and heartbeat only
./telegraf_controller --disable-auth-endpoints=agents,heartbeat
# Disable auth for all endpoints
./telegraf_controller --disable-auth-endpoints="*"
```
These values are used as initial defaults when {{% product-name %}} creates its settings record for the first time.
After that, changes made through the **Settings** page take precedence.
## Login security
### Login attempts
You can configure the number of failed login attempts allowed before an account is locked out.
The default threshold is 5 attempts, with a minimum of 1.
To change the login attempt threshold:
1. Navigate to the **Settings** page.
2. Update the **Login attempts** value.
3. Click **Save**.
### Login lockout
When a user exceeds the failed attempt threshold, their account is locked for a configurable duration.
The default lockout duration is 15 minutes, with a minimum of 1 minute.
The lockout clears automatically after the configured duration has elapsed.
To change the lockout duration:
1. Navigate to the **Settings** page.
2. Update the **Login lockout duration** value.
3. Click **Save**.
> [!Tip]
> If a user is locked out, an owner or administrator can [reset their password](/telegraf/controller/users/update/#reset-a-users-password) to unlock the account.
### Password complexity requirements
{{% product-name %}} provides three password complexity levels that apply to all
password operations, including initial setup, password changes, password resets,
and invite completion.
| Level | Min length | Uppercase* | Lowercase* | Digits* | Special characters* |
| :--------- | :--------: | :--------: | :--------: | :-----: | :-----------------: |
| **Low** | 8 | No | No | No | No |
| **Medium** | 10 | Yes | Yes | Yes | No |
| **High** | 12 | Yes | Yes | Yes | Yes |
{{% caption %}}
\* Passwords require at least one of the defined character types.
{{% /caption %}}
To change the password complexity level:
1. Navigate to the **Settings** page.
2. Select the desired **Password complexity** level.
3. Click **Save**.
> [!Note]
> Changing the password complexity level does not affect existing passwords. The new requirements apply only when users set or change their passwords.
### Environment variables
You can set initial defaults for login security settings using environment variables.
These values are applied when {{% product-name %}} initializes its settings for the first time.
Changes made on the **Settings** page override initialized settings.
| Environment variable | Description | Default |
| :----------------------- | :----------------------------------------- | :-----: |
| `LOGIN_LOCKOUT_ATTEMPTS` | Failed attempts before lockout | `5` |
| `LOGIN_LOCKOUT_MINUTES` | Minutes to lock account | `15` |
| `PASSWORD_COMPLEXITY` | Complexity level (`low`, `medium`, `high`) | `low` |

View File

@ -0,0 +1,69 @@
---
title: Manage API tokens
description: >
Create and manage API tokens for authenticating API requests and
Telegraf agent connections to Telegraf Controller.
menu:
telegraf_controller:
name: Manage API tokens
weight: 8
cascade:
related:
- /telegraf/controller/reference/authorization/
---
API tokens authenticate requests to the {{% product-name %}} API and Telegraf agent connections.
Use tokens to authorize Telegraf agents, heartbeat requests, and external API clients.
## Token format
All API tokens use the `tc-apiv1_` prefix, making them easy to identify in
configuration files and scripts.
The full token value is displayed only once at the time of creation and cannot be retrieved later.
Copy and store the token in a secure location immediately after creating it.
> [!Important]
> #### Raw token strings are not stored
>
> Tokens are stored as a cryptographic hash. The original value is never saved.
> If you lose a token, you must revoke it and create a new one.
## Token permissions
Each token is scoped to a specific user.
Token permissions are restricted to the permissions allowed by the user's role.
A token cannot exceed the permissions of the user it belongs to.
When you create a token, you can set custom permissions to restrict the token's
access below your full role permissions.
This lets you issue narrowly scoped tokens for specific tasks, such as a token
that can only register agents or a token limited to read-only access.
## Token states
Tokens exist in one of two states:
- **Active** -- The token can be used for authentication.
- **Revoked** -- The token is permanently disabled but the record is retained
for auditing purposes.
Revoking a token is irreversible.
Any agent or client using a revoked token immediately loses access.
## Token visibility
Your role determines which tokens you can view and manage:
| Role | Token visibility |
|:------------------|:----------------------------------|
| **Owner** | All tokens across all users |
| **Administrator** | All tokens across all users |
| **Manager** | Only their own tokens |
| **Viewer** | Cannot manage tokens |
> [!Note]
> **Owner** and **Administrator** users can revoke any token in the organization,
> including tokens belonging to other users.
{{< children hlevel="h2" >}}

View File

@ -0,0 +1,63 @@
---
title: Create an API token
description: >
Create a new API token for authenticating with the Telegraf Controller API.
menu:
telegraf_controller:
name: Create a token
parent: Manage API tokens
weight: 101
---
Create a new API token to authenticate requests to the {{% product-name %}} API.
Tokens let you grant scoped access to external tools, scripts, and services without sharing your login credentials.
> [!Important]
> #### Required permissions
>
> You must have an **Owner**, **Administrator**, or **Manager** role assigned to
> your account.
## Create a token
1. Navigate to the **API Tokens** page.
2. Click **Create Token**.
3. Enter a **Description** for the token that identifies where or how the token
will be used.
4. _(Optional)_ Set an **Expiration** date.
Tokens without an expiration date remain active indefinitely.
5. _(Optional)_ Set **Custom permissions** to restrict the token's access below
your role's full permissions.
See [Custom permissions](#custom-permissions) for details.
6. Click **Create**.
{{< img-hd src="/img/telegraf/controller-create-token.png" alt="Telegraf Controller create token form" />}}
> [!Important]
> #### Copy and store your token
>
> Copy your API token immediately after creation.
> The full token value is only displayed once and cannot be retrieved later.
## Custom permissions
When you set custom permissions on a token, {{% product-name %}} intersects
those permissions with your role's existing permissions.
This means you can use custom permissions to narrow a token's access, but you
cannot create a token with more access than your role allows.
For example, if you have the **Manager** role, you cannot create a token with
user management permissions.
The resulting token will only include the permissions that overlap with what
your role grants.
Custom permissions are useful when you want to issue a token for a specific task,
such as read-only access to configurations, without exposing the full scope of
your role.
## If you lose a token
If you lose or forget a token value, you cannot recover it.
Revoke the lost token and create a new one to restore access.
For instructions on revoking a token, see [Revoke an API token](/telegraf/controller/tokens/revoke/).

View File

@ -0,0 +1,60 @@
---
title: Delete a token
description: >
Permanently delete an API token from Telegraf Controller.
menu:
telegraf_controller:
name: Delete a token
parent: Manage API tokens
weight: 105
---
Deleting a token immediately removes the token so it cannot be used for authentication.
Unlike revocation, deletion removes all data associated with the token and token
history.
> [!Warning]
> #### Deleting and API token cannot be undone
>
> Deleting a token is permanent and cannot be undone. Any agents or clients
> using this token will lose access immediately.
## Delete versus revoke
{{% product-name %}} supports two ways to remove a token from active use:
**deletion** and **revocation**.
- **Deleted** tokens are permanently removed from the system.
No record of the token is retained after deletion.
- **Revoked** tokens remain visible in the token list with a **Revoked** status.
This provides an audit trail showing when the token was created and when it
was disabled. Revoked tokens cannot be used for authentication.
Use revoke when you want to disable a token but maintain an audit trail.
Use delete when you want to completely remove the token and its record from the system.
For more information about revoking a token, see
[Revoke a token](/telegraf/controller/tokens/revoke/).
## Delete a token
1. Navigate to the **API Tokens** page or open the token's detail view.
2. Click **Delete** to initiate the deletion. If on the token detail
page, select the **Manage** tab to reveal the **Delete** action.
3. In the confirmation dialog, confirm that you want to permanently delete the token.
Once confirmed, the token is immediately deleted. Any agent or integration
that relies on the deleted token will no longer be able to authenticate with
{{% product-name %}}.
## Bulk delete tokens
You can delete multiple tokens at once from the **API Tokens** page.
1. On the **API Tokens** page, select the checkboxes next to each token you want to delete.
2. Click the **Delete** option in the bulk actions bar.
3. In the confirmation dialog, review the number of tokens to be deleted and confirm.
All selected tokens are permanently removed and immediately invalidated.
Verify that no active agents depend on the selected tokens before confirming the
bulk deletion.

View File

@ -0,0 +1,64 @@
---
title: Reassign a token
description: >
Reassign an API token from one user to another in Telegraf Controller.
menu:
telegraf_controller:
name: Reassign a token
parent: Manage API tokens
weight: 103
---
Reassigning an API token from one user to another in Telegraf Controller lets
you transfer ownership of that token to another user without disrupting any
external clients using the token.
> [!Important]
> #### Required permissions
>
> To reassign an API token, you must have the **Owner** or **Administrator**
> role in {{% product-name %}}.
## Reassign a token
You can reassign an individual token from one user to another directly from the
token's detail view or the tokens list.
1. In {{% product-name %}}, navigate to the **API Tokens** page or open the
detail page for the token you want to reassign.
2. Click **Reassign** on the token you want to transfer. If on the token detail
page, select the **Manage** tab to reveal the **Reassign** action.
3. In the dialog that appears, select the target user you want to assign the
token to.
4. Click **Confirm** to complete the reassignment.
> [!Important]
> When you reassign a token, its permissions are automatically restricted to
> match the target user's role. For example, a token with full access reassigned
> to a Viewer becomes a read-only token.
## Bulk reassign
If you need to reassign multiple tokens at once, use the bulk reassign option.
1. On the **API Tokens** page, select the checkboxes next to the tokens you want
to reassign.
2. Click the **Reassign** option in the bulk actions bar.
3. Select the target user you want to assign the selected tokens to.
4. Click **Confirm** to reassign all selected tokens.
The same permission restriction applies during bulk reassignment. Each token's
permissions are adjusted to align with the target user's role.
## When to reassign
Reassigning tokens lets you transfer ownership without revoking and recreating
tokens. This is useful in several common scenarios:
- **Offboarding a user**: A user is leaving the organization and their tokens
should continue working under another account.
Reassigning ensures active integrations are not disrupted.
- **Reorganizing responsibilities**: Team members are shifting roles or
responsibilities and token ownership should reflect the new structure.
- **Consolidating ownership after role changes**: After updating user roles, you
may want to consolidate tokens under a single account to simplify token management.

View File

@ -0,0 +1,61 @@
---
title: Revoke a token
description: >
Revoke an API token to immediately prevent its use while keeping
the token record for auditing.
menu:
telegraf_controller:
name: Revoke a token
parent: Manage API tokens
weight: 104
---
Revoking a token immediately prevents it from being used for authentication
while keeping the token record in the system for auditing purposes.
Unlike deletion, revocation preserves a full history of the token, including
when it was created and when it was disabled.
## Revoke versus delete
{{% product-name %}} supports two ways to remove a token from active use:
**revocation** and **deletion**.
- **Revoked** tokens remain visible in the token list with a **Revoked** status.
This provides an audit trail showing when the token was created and when it
was disabled. Revoked tokens cannot be used for authentication.
- **Deleted** tokens are permanently removed from the system.
No record of the token is retained after deletion.
Use revoke when you want to disable a token but maintain an audit trail.
Use delete when you want to completely remove the token and its record from the system.
For more information about deleting a token, see
[Delete a token](/telegraf/controller/tokens/delete/).
## Revoke a token
1. Navigate to the **API Tokens** page, or open the token's detail view.
2. Click **Revoke**. If on the token detail page, select the **Manage** tab to
reveal the **Revoke** action.
3. Confirm the revocation in the dialog.
The token status changes to **Revoked** and any requests that use the token are
immediately rejected.
> [!Note]
> #### You cannot reactivate a revoked token
>
> Revocation is permanent. You cannot re-activate a revoked token.
> If you need to restore access, create a new token.
> See [Create a token](/telegraf/controller/tokens/create/).
## Bulk revoke
To revoke multiple tokens at once:
1. On the **API Tokens** page, select the tokens you want to revoke.
2. Click **Revoke** in the bulk actions bar.
3. Confirm the revocation in the dialog.
All selected tokens are immediately revoked and can no longer be used for
authentication.

View File

@ -0,0 +1,81 @@
---
title: Use API tokens
description: >
Use API tokens to authenticate Telegraf agents, heartbeat requests,
and external API clients with Telegraf Controller.
menu:
telegraf_controller:
name: Use tokens
parent: Manage API tokens
weight: 102
---
API tokens authenticate requests to {{% product-name %}}.
Use tokens to connect Telegraf agents, authorize heartbeat reporting, and
integrate external API clients.
## With Telegraf agents
Configure your Telegraf agent to include an API token when retrieving
configurations and reporting heartbeats to {{% product-name %}}.
Telegraf agents require API tokens with the following permissions:
- **Configs**: Read
- **Heartbeat**: Write
### Use the INFLUX_TOKEN environment variable
When retrieving a configuration from a URL, Telegraf only sends an `Authorization`
when it detects the `INFLUX_TOKEN` environment variable. To authorize Telegraf
to retrieve a configuration from {{% product-name %}}, define the `INFLUX_TOKEN`
environment variable:
<!--pytest.mark.skip-->
```bash { placeholders="YOUR_TC_API_TOKEN" }
export INFLUX_TOKEN=YOUR_TC_API_TOKEN
telegraf \
--config "http://telegraf_controller.example.com/api/configs/xxxxxx/toml
```
Replace {{% code-placeholder-key %}}`YOUR_TC_API_TOKEN`{{% /code-placeholder-key %}}
with your {{% product-name %}} API token.
### For heartbeat requests
Telegraf uses the [Heartbeat output plugin](/telegraf/v1/output-plugins/heartbeat/)
to send heartbeats to {{% product-name %}}.
Use the `INFLUX_TOKEN` environment variable to define the `token` option in your
heartbeat plugin configuration.
Telegraf uses the environment variable value defined when starting Telegraf.
```toml { .tc-dynamic-values }
[[outputs.heartbeat]]
url = "http://telegraf_controller.example.com/agents/heartbeat"
instance_id = "&{agent_id}"
interval = "1m"
include = ["hostname", "statistics", "configs"]
token = "${INFLUX_TOKEN}"
```
When authentication is required for the heartbeat endpoint, agents must include
a valid token with each heartbeat request.
If a heartbeat request is missing a token or includes an invalid token,
{{% product-name %}} rejects the request and the agent's status is not updated.
## With external API clients
Include the token in the `Authorization` header when making API requests to
{{% product-name %}}:
```
Authorization: Bearer tc-apiv1_<token>
```
The token's permissions determine which API endpoints and operations are accessible.
Requests made with a token that lacks the required permissions are rejected with an authorization error.
> [!Note]
> If authentication is disabled for an endpoint group in **Settings**, requests to those endpoints do not require a token.
> See [Settings](/telegraf/controller/settings/#require-authentication-per-endpoint) for details on configuring authentication requirements per endpoint.

View File

@ -0,0 +1,46 @@
---
title: Manage users
description: >
Manage user accounts in Telegraf Controller, including creating, updating,
disabling, and deleting users.
menu:
telegraf_controller:
name: Manage users
weight: 7
cascade:
related:
- /telegraf/controller/reference/authorization/
---
Users are accounts that can log into the {{% product-name %}} web interface and
interact with the system based on their assigned role.
You can create, update, disable, and delete users to control who has access to
your {{% product-name %}} instance.
## User states
Each user account is in one of the following states:
- **Active** --- The user can log in and perform actions based on their assigned
role.
- **Disabled** --- The user cannot log in. Existing API tokens remain associated
with the account but are unusable while the user is disabled.
- **Locked** --- A temporary state triggered by too many failed login attempts.
The lock clears automatically after the configured lockout period. See the
[Settings](/telegraf/controller/settings/) page for configuration options.
## User roles
{{% product-name %}} supports four roles with different levels of access:
| Role | Access level |
|:------------------|:--------------------------------------------------------------------|
| **Owner** | Full access. Manages users, tokens, and settings. |
| **Administrator** | Full access except ownership transfer. |
| **Manager** | Manages configs, agents, labels, reporting rules, and own tokens. |
| **Viewer** | Read-only access. |
For more details about roles and permissions, see
[Authorization](/telegraf/controller/reference/authorization/).
{{< children hlevel="h2" >}}

View File

@ -0,0 +1,54 @@
---
title: Manage your account
description: >
Update your username, email address, and password in Telegraf Controller.
menu:
telegraf_controller:
name: Manage your account
parent: Manage users
weight: 101
---
Any authenticated user can update their own account details from the account page.
Use the account page to change your username, email address, or password at any time.
{{< img-hd src="/img/telegraf/controller-account-page.png" alt="Telegraf Controller account page" />}}
## Update your username
Your username is your display name throughout {{% product-name %}}.
Each username must be unique across the system.
1. Click your profile icon in the top-right corner and select **Account**.
2. In the **Username** field, enter your new username.
3. Click **Save**.
If the username you entered is already taken, {{% product-name %}} displays an
error. Choose a different username and try again.
## Update your email address
Each email address must be unique and in a valid format.
1. Click your profile icon in the top-right corner and select **Account**.
2. In the **Email** field, enter your new email address.
3. Click **Save**.
If the email address is already associated with another account or is not in a
valid format, {{% product-name %}} displays an error.
Correct the email address and try again.
## Update your password
To change your password, you must provide your current password along with the
new one.
1. Click your profile icon in the top-right corner and select **Account**.
2. In the **Current Password** field, enter your existing password.
3. In the **New Password** field, enter your new password.
4. In the **Confirm Password** field, re-enter the new password.
5. Click **Save**.
> [!Note]
> Your new password must meet the password complexity requirements configured by your administrator.
> For more information, see [Password requirements](/telegraf/controller/settings/#password-requirements).

View File

@ -0,0 +1,48 @@
---
title: Delete a user
description: >
Permanently delete a user account and all associated API tokens from
Telegraf Controller.
menu:
telegraf_controller:
name: Delete a user
parent: Manage users
weight: 106
---
> [!Warning]
> #### Deleting a user cannot be undone
>
> Deleting a user is permanent and cannot be undone.
> All of the user's API tokens are also deleted.
## What deletion removes
When you delete a user from {{% product-name %}}, the following are permanently
removed:
- User account and credentials
- All API tokens owned by the user
- All active sessions
## Delete a user
1. In the {{% product-name %}} UI, navigate to **Users** and click the user you
want to delete to open their detail page.
2. Click **Delete User**.
3. In the confirmation dialog, confirm the deletion.
The user is immediately removed and can no longer authenticate with
{{% product-name %}}.
## Restrictions
- You cannot delete your own account.
- You cannot delete the owner — you must
[transfer ownership](/telegraf/controller/users/transfer-ownership/) first.
- Only the owner can delete administrator accounts.
> [!Tip]
> If you're unsure whether to delete a user, consider
> [disabling them](/telegraf/controller/users/disable/) first.
> Disabled accounts can be re-enabled later.

View File

@ -0,0 +1,41 @@
---
title: Disable a user
description: >
Disable a user account to prevent login without deleting the account
or its associated tokens.
menu:
telegraf_controller:
name: Disable a user
parent: Manage users
weight: 105
---
Disabling a user prevents them from logging in without permanently deleting their account or tokens.
This is useful when you want to temporarily revoke access or are unsure whether to delete the account.
## What disabling does
When you disable a user account in {{% product-name %}}:
- The user cannot log in to the web interface.
- All active sessions are destroyed immediately.
- Existing API tokens remain in the system but cannot be used for authentication
while the user is disabled.
- The user's data (account details, token records) is preserved.
## Disable a user
1. Navigate to the user's detail page.
2. Toggle the user's status to **Disabled** (or click the **Disable** option).
3. Confirm the action.
> [!Note]
> You cannot disable your own account or the **Owner** account.
## Re-enable a user
1. Navigate to the disabled user's detail page.
2. Toggle the user's status to **Active** (or click the **Enable** option).
Once re-enabled, the user can log in immediately with their existing credentials.
Their API tokens also become usable again.

View File

@ -0,0 +1,76 @@
---
title: Invite a new user
description: >
Invite new users to Telegraf Controller by generating an invite link with
a pre-assigned role.
menu:
telegraf_controller:
name: Invite a new user
parent: Manage users
weight: 102
---
Owners and administrators can invite new users to {{% product-name %}} by
generating an invite link with a pre-assigned role and expiration.
The invited user opens the link, sets a password, and their account is
immediately active.
> [!Note]
> You must have the **Owner** or **Administrator** role to create invites.
## Create an invite
1. Navigate to the **Users** page.
2. Click the {{% icon "plus" %}} **Invite User** button.
3. Enter a **Username** for the new user (3--50 characters).
4. Enter the user's **Email** address.
5. Select a **Role** for the new user:
- **Administrator** -- full access to all resources and user management.
- **Manager** -- can manage configurations, agents, and labels but cannot
manage users.
- **Viewer** -- read-only access to all resources.
6. Set the invite **Expiration** in hours. The default is 72 hours. Valid
values range from 1 to 720 hours (30 days).
7. Click **Create Invite**.
{{< img-hd src="/img/telegraf/controller-invite-user.png" alt="Telegraf Controller invite user form" />}}
> [!Note]
> You cannot invite a user with the **Owner** role. To make someone the owner,
> first invite them as an **Administrator**, then
> [transfer ownership](/telegraf/controller/users/transfer-ownership/).
## Share the invite link
After creating the invite, {{% product-name %}} displays a unique invite link.
Copy the link and share it with the user through your preferred communication
channel (email, chat, etc.).
The link expires after the duration you configured. Once expired, the link can
no longer be used and you must create a new invite.
## Accept an invite
The invited user completes the following steps to activate their account:
1. Open the invite link in a browser.
2. Set a password that meets the configured complexity requirements.
3. Click **Create Account**.
The account activates immediately and the user is automatically logged in with
the role assigned during the invite.
## Manage pending invites
You can view and manage all pending invites from the **Users** page.
Pending invites appear in a separate list above active users.
To revoke a pending invite before it is used:
1. Navigate to the **Users** page.
2. Locate the pending invite you want to remove.
3. Click the **Delete** button next to the invite.
4. Confirm the deletion when prompted.
Deleting a pending invite invalidates the invite link. The invited user can no
longer use it to create an account.

View File

@ -0,0 +1,57 @@
---
title: Transfer ownership
description: >
Transfer the Telegraf Controller owner role to another administrator.
menu:
telegraf_controller:
name: Transfer ownership
parent: Manage users
weight: 104
---
The **Owner** role grants full administrative access to {{% product-name %}},
including the ability to manage all users, tokens, and settings. Only one owner
can exist at a time. The current owner can transfer ownership to any active
administrator.
## Prerequisites and restrictions
- Only the current **Owner** can transfer ownership.
- The target user must have the **Administrator** role and be in an active state.
- If the target user is a **Manager** or **Viewer**, you must first promote them
to **Administrator**. See
[Change a user's role](/telegraf/controller/users/update/#change-a-users-role).
- You cannot transfer ownership to yourself.
## Transfer the owner role
1. Navigate to the **Users** page or the target user's detail page.
2. Choose the target **Administrator** from the list (if not already selected).
3. Select the **Make Owner** option. If on the user detail page, select the
**Manage** tab to reveal the **Make Owner** option.
4. Confirm the username of the user you want to transfer ownership to and click
**Transfer Ownership**.
{{< img-hd src="/img/telegraf/controller-transfer-ownership.png" alt="Telegraf Controller transfer ownership confirmation" />}}
## What happens during transfer
When you confirm the transfer, {{% product-name %}} performs an atomic operation
that updates both accounts simultaneously:
- The current owner is demoted to **Administrator**.
- The target user is promoted to **Owner**.
- Both users' sessions are destroyed -- both must log in again.
- The operation is atomic: both changes succeed together or neither takes effect.
> [!Tip]
> #### Coordinate ownership transfers
>
> Coordinate with the target user before transferring ownership. Both accounts
> are logged out immediately after the transfer completes.
> [!Warning]
> #### You cannot reclaim the Owner role yourself
>
> Once transferred, you cannot reclaim the **Owner** role yourself. The new
> owner must transfer it back to you.

View File

@ -0,0 +1,84 @@
---
title: Update users
description: >
Reset user passwords, change user roles, and manage user accounts in
Telegraf Controller.
menu:
telegraf_controller:
name: Update users
parent: Manage users
weight: 103
---
Owners and administrators can reset passwords and change roles for other users in {{% product-name %}}.
These actions help maintain account security and ensure users have the appropriate level of access.
## Reset a user's password
When a user forgets their password or needs a credential refresh, you can
generate a time-limited reset link for them.
> [!Note]
> You must have the **Owner** or **Administrator** role to reset passwords.
> Only the **Owner** can reset **Administrator** passwords.
### Generate a password reset link
1. Navigate to the user's detail page.
2. Click **Reset Password**.
3. Set the link expiration. The default is 24 hours, but you can configure it from 1 to 720 hours.
4. Click **Generate Link** to create the reset link.
5. Copy the generated reset link and share it with the user through a secure channel.
### Complete a password reset
After receiving a reset link, the user completes the following steps:
1. Open the reset link in a browser.
2. Enter a new password that meets the complexity requirements.
3. Click **Submit** to save the new password.
> [!Note]
> The user is not automatically logged in after resetting their password.
> They must log in with their new credentials.
### Emergency owner password reset
If the owner account is locked out or the owner has forgotten their password,
you can reset it using environment variables.
1. Set the following environment variables:
- `RESET_OWNER_PASSWORD=true`
- `OWNER_PASSWORD` to the desired new password
2. Restart the {{% product-name %}} application.
3. Log in with the new password.
4. Remove the `RESET_OWNER_PASSWORD` and `OWNER_PASSWORD` environment variables.
> [!Warning]
> Remove `RESET_OWNER_PASSWORD` and `OWNER_PASSWORD` environment variables after successfully logging in. Leaving them set causes the password to reset on every application restart.
## Change a user's role
You can promote or demote users by changing their assigned role.
> [!Note]
> You must have the **Owner** or **Administrator** role to change a user's role.
> Only the **Owner** can change a user's role to **Administrator**.
1. Navigate to the user's detail page.
2. Select the user's new role.
3. Confirm the change when prompted.
The following restrictions apply to role changes:
- You cannot assign the **Owner** role directly. To make a user the owner,
the current owner must [transfer ownership](/telegraf/controller/users/transfer-ownership/).
> [!Important]
> #### Side effects of changing a user's role
>
> - The user's API tokens are reclamped to match the new role's permissions.
> If the new role cannot manage tokens (such as **Viewer**), all active tokens
> are revoked.
> - The user's active sessions are destroyed. They must log in again to continue
> using {{% product-name %}}.

View File

@ -0,0 +1,103 @@
/// <reference types="cypress" />
/**
* E2E tests for the Telegraf Controller gated downloads module (tc-downloads.js).
*
* Tests the four key user-facing behaviors:
* 1. Gated state no localStorage key button visible, links hidden
* 2. Ungated state localStorage key present links rendered, button hidden
* 3. Query param ?ref=tc visit key set, downloads shown
* 4. SHA copy button present when downloads are rendered
*
* Marketo form submission is NOT tested (external dependency).
*/
const PAGE_URL = '/telegraf/controller/install/';
const STORAGE_KEY = 'influxdata_docs_tc_dl';
describe('Telegraf Controller gated downloads', () => {
describe('Gated state (no localStorage key)', () => {
beforeEach(() => {
// Clear any existing key so the page starts in the gated state.
cy.clearLocalStorage();
cy.visit(PAGE_URL);
});
it('shows the download button', () => {
cy.get('#tc-download-btn').should('be.visible');
});
it('keeps the download links container hidden', () => {
cy.get('#tc-downloads-links').should('not.be.visible');
});
it('does not render download link anchors', () => {
cy.get('.tc-download-link').should('not.exist');
});
});
describe('Ungated state (localStorage key present)', () => {
beforeEach(() => {
cy.clearLocalStorage();
cy.visit(PAGE_URL, {
onBeforeLoad(win) {
win.localStorage.setItem(STORAGE_KEY, 'true');
},
});
});
it('hides the download button', () => {
cy.get('#tc-download-btn').should('not.be.visible');
});
it('shows the downloads container', () => {
cy.get('#tc-downloads-links').should('be.visible');
});
it('renders at least one download link', () => {
cy.get('.tc-download-link').should('have.length.at.least', 1);
});
it('renders SHA copy buttons for each build', () => {
cy.get('.tc-copy-sha').should('have.length.at.least', 1);
});
});
describe('Query param flow (?ref=tc)', () => {
beforeEach(() => {
cy.clearLocalStorage();
cy.visit(`${PAGE_URL}?ref=tc`);
});
it('sets the localStorage key', () => {
cy.window().then((win) => {
expect(win.localStorage.getItem(STORAGE_KEY)).to.equal('true');
});
});
it('shows download links after the param is processed', () => {
cy.get('.tc-download-link').should('have.length.at.least', 1);
});
it('strips the ?ref=tc param from the URL', () => {
cy.url().should('not.include', 'ref=tc');
});
});
describe('SHA copy button', () => {
beforeEach(() => {
cy.clearLocalStorage();
cy.visit(PAGE_URL, {
onBeforeLoad(win) {
win.localStorage.setItem(STORAGE_KEY, 'true');
},
});
});
it('each copy button carries a data-sha attribute', () => {
cy.get('.tc-copy-sha').each(($btn) => {
expect($btn.attr('data-sha')).to.be.a('string').and.not.be.empty;
});
});
});
});

View File

@ -40,6 +40,42 @@
# - [The plan for InfluxDB 3.0 Open Source](https://influxdata.com/blog/the-plan-for-influxdb-3-0-open-source)
# - [InfluxDB 3.0 benchmarks](https://influxdata.com/blog/influxdb-3-0-is-2.5x-45x-faster-compared-to-influxdb-open-source/)
- id: telegraf-enterprise-beta
level: note
scope:
- /
exclude:
- /platform/
- /resources/
- /kapacitor/
- /chronograf/
- /enterprise_influxdb/
- /influxdb3/
- /influxdb/
- /flux/
title: Telegraf Enterprise now in public beta
slug: |
Get early access to the **Telegraf Controller** and provide feedback to help
shape the future of **Telegraf Enterprise**.
<a class="btn" href="https://www.influxdata.com/blog/telegraf-enterprise-beta">See the Blog Post</a>
message: |
The upcoming Telegraf Enterprise offering is for organizations running
Telegraf at scale and is comprised of two key components:
- **Telegraf Controller**: A control plane (UI + API) that centralizes Telegraf configuration management and agent health visibility.
- **Telegraf Enterprise Support**: Official support for Telegraf Controller and Telegraf plugins.
<a href="https://influxdata.com/products/telegraf-enterprise" target="_blank">Join the Telegraf Enterprise beta</a>
to get early access to the Telegraf Controller and provide feedback to help
shape the future of Telegraf Enterprise.
For more information:
- [See the announcement blog post](https://www.influxdata.com/blog/telegraf-enterprise-beta)
- [Telegraf Controller Documentation](/telegraf/controller/)
- [Download and install Telegraf Controller](/telegraf/controller/install/)
- id: influxdb3.8-explorer-1.6
level: note
scope:

24
data/tc_downloads.yml Normal file
View File

@ -0,0 +1,24 @@
version: "0.0.5-beta"
platforms:
- name: Linux
builds:
- arch: x64
os: linux
sha256: "854592b5e1f1922774074036650ed94fc278d9a666b20d35c98e75defb56d2cf"
- arch: arm64
os: linux
sha256: "15ea90cc93bc345ce77e4b7eb15efa36522efb7026433f25098280fb6577ca91"
- name: macOS
builds:
- arch: x64
os: macos
sha256: "3ac978da3619f396b78fe51db32cbcc6365af41b6e53ad28eec393eccf3a53a2"
- arch: arm64
os: macos
sha256: "5c64a3dd3b211cbb0fa3b1e833ca0cb88bbf32209802533b138018a939892562"
- name: Windows
builds:
- arch: x64
os: win
ext: .exe
sha256: "b98d5034d8cbeb84efeed754688906500c528a54b70fdb33a338a60f13316f94"

View File

@ -5,5 +5,9 @@
{{ $withPlaceholders := replaceRE .Attributes.placeholders $elReplace $highlightedCode }}
{{ $withPlaceholders | safeHTML }}
{{ else }}
{{ $result.Wrapped }}
{{ end }}
{{- $wrapped := string $result.Wrapped -}}
{{- if in $wrapped "tc-dynamic-values" -}}
{{- $wrapped = replace $wrapped "tc-dynamic-values" "tc-dynamic-values\" data-component=\"tc-dynamic-values" -}}
{{- end -}}
{{ $wrapped | safeHTML }}
{{ end }}

View File

@ -128,12 +128,29 @@
<div class="bg-overlay"></div>
<div class="product-info">
<h2>Collect data with Telegraf</h2>
<p>The data collection agent that supports a large catalog of data sources and targets.</p>
</div>
<ul class="product-links">
<li><a href="/telegraf/v1/get-started/">Get started with Telegraf</a></li>
<li><a href="/telegraf/v1/plugins/">View Telegraf plugins</a></li>
</ul>
<div class="products">
<div class="product">
<div class="product-info">
<h3><a href="/telegraf/v1/">Telegraf <span class="version">{{ $telegrafVersion }}</span></a></h3>
<p>The open source data collection agent with support for a large catalog of data sources and targets.</p>
</div>
<ul class="product-links">
<li><a href="/telegraf/v1/get-started/">Get started with Telegraf</a></li>
<li><a href="/telegraf/v1/plugins/">View Telegraf plugins</a></li>
</ul>
</div>
<div class="product">
<div class="product-info">
<h3 state="beta"><a href="/telegraf/controller/">Telegraf Controller</a></h3>
<p>Centralized Telegraf configuration management and agent observability with an intuitive UI.</p>
</div>
<ul class="product-links">
<li><a href="/telegraf/controller/install/">Download and Install</a></li>
<li><a href="/telegraf/controller/">View documentation</a></li>
</ul>
</div>
</div>
</div>
<div id="influxdbv2" class="product-group">
@ -201,16 +218,6 @@
<div id="other" class="product-group">
<h2>Other Products</h2>
<div class="products">
<div class="product">
<div class="product-info">
<h3><a href="/telegraf/v1/">Telegraf <span class="version">{{ $telegrafVersion }}</span></a></h3>
<p>The collection agent that gathers time series data from many different sources.</p>
</div>
<ul class="product-links">
<li><a href="/telegraf/v1/get-started/">Get started with Telegraf {{ $telegrafVersion }}</a></li>
<li><a href="/telegraf/v1/plugins/">View Telegraf plugins</a></li>
</ul>
</div>
<div class="product">
<div class="product-info">
<h3><a href="/chronograf/v1/">Chronograf <span class="version">{{ $chronografVersion }}</span></a></h3>

View File

@ -18,21 +18,63 @@
{{ if in $productPathWhitelist (print $product "/" $version )}}
<div class="block special-state">
<div class="state-content">
<h4 id="telegraf-controller-private-alpha">{{ $displayName }} is in Private Alpha</h4>
<h4 id="telegraf-controller-public-beta">{{ $displayName }} is in Public Beta</h4>
<p>
{{ $displayName }} is in private alpha. If you are interested in being a
part of the private alpha program, please sign up:
</p>
<p><a href="https://www.influxdata.com/products/telegraf-enterprise" class="btn">Sign Up for the Alpha</a></p>
<p>
While in alpha, {{ $displayName }} is <strong>not meant for production use</strong>.
{{ $displayName }} is in public beta and will be part of the future Telegraf Enterprise offering.
While in beta, {{ $displayName }} is <strong>not meant for production use</strong>.
The {{ $displayName}} documentation is a work in progress, and we are actively
working to improve it. If you have any questions or suggestions, please
<a href="https://github.com/influxdata/docs-v2/issues/new?labels=Telegraf%20Controller">submit an issue</a>.
We welcome any and all contributions.
</p>
<div class="expand-wrapper">
<div class="expand" id="feedback-channels">
<div class="expand" id="beta-expecations">
<p class="expand-label">
<span class="expand-toggle"></span><span>Beta expectations</span>
</p>
<div class="expand-content" style="display: none;" >
<ul>
<li>
<strong>No configuration or agent limits</strong> <br/>
While in beta, {{ $displayName }} doesn't place any limits on the
number of configurations you can store or the number of Telegraf
agents you can track. However, upon being generally available,
the free distribution of {{ $displayName }} will have limits
introduced, with the option to increase limits through a
Telegraf Enterprise license.
</li>
<li>
<strong>Potential breaking changes</strong> <br/>
While in beta, we will do our best to no longer make breaking
changes to {{ $displayName }}, however, they may be necessary.
The majority of changes we make will be additive and non-breaking,
and include any necessary migrations. When we do need to make
breaking changes, we will do our best to communicate them clearly
and in advance to minimize disruption.
</li>
<li>
<strong>Flexible release schedule</strong> <br/>
While in beta, we will continue to create new releases of
{{ $displayName }}, but likely at irregular intervals. We will provide
<a href="/telegraf/controller/reference/release-notes/">Telegraf Controller release notes</a>
to make it easy to track updates.
</li>
</ul>
</div>
</div>
<div class="expand" id="beta-provide-feedback">
<p class="expand-label">
<span class="expand-toggle"></span><span>Provide beta feedback</span>
</p>
<div class="expand-content" style="display: none;" >
<ul>
<li>Use the <strong>Feedback</strong> feature in the Telegraf Controller UI.</li>
<li><a href="https://influxdata.com/slack" target="_blank">Join the InfluxDB Community Slack</a> and post feedback in the <strong>#telegraf-enterprise-alpha</strong> channel.</li>
<li>Post feedback in the <a href="https://community.influxdata.com" target="_blank">InfluxData Community</a>.</li>
</ul>
</div>
</div>
<div class="expand" id="public-channels">
<p class="expand-label">
<span class="expand-toggle"></span><span>Join our public channels</span>
</p>

View File

@ -14,6 +14,9 @@
{{ if $inStdlib }}
{{ partial "footer/modals/flux-influxdb-versions.html" . }}
{{ end }}
{{ if .Page.HasShortcode "telegraf/tc-downloads" }}
{{ partial "footer/modals/tc-downloads.html" . }}
{{ end }}
</div>
</div>
</div>

View File

@ -0,0 +1,11 @@
<div class="modal-content" id="tc-downloads">
<h3>Download Telegraf Controller</h3>
<p>Provide your information to access Telegraf Controller downloads.</p>
<script src="https://get.influxdata.com/js/forms2/js/forms2.min.js"></script>
<form id="mktoForm_3195"></form>
<div class="tc-form-error" style="display: none;">
An error occurred. Please try again.
</div>
</div>

View File

@ -35,6 +35,8 @@
{{ .Scratch.Set "searchPlaceholder" "Search the docs" }}
{{ else if (eq $currentVersion nil) }}
{{ .Scratch.Set "searchPlaceholder" (print "Search " (index .Site.Data.products $product).name) }}
{{ else if (eq $product "telegraf") }}
{{ .Scratch.Set "searchPlaceholder" (print "Search " (cond (eq $currentVersion "v1") "Telegraf" "Telegraf Controller")) }}
{{ else if eq $product "influxdb" }}
{{ if eq $currentVersion "v3" }}
{{ .Scratch.Set "searchPlaceholder" "Search InfluxDB OSS v3" }}

View File

@ -90,7 +90,7 @@ Identify products by their product path. Dictionary schema:
<div class="group-title"><p>Telegraf</p></div>
<ul class="item-list products">
<li>{{ template "productLink" (merge (dict "productPath" "telegraf/v1") $templateDefaults) }}</li>
<li>{{ template "productLink" (merge (dict "productPath" "telegraf/controller" "state" "alpha") $templateDefaults) }}</li>
<li>{{ template "productLink" (merge (dict "productPath" "telegraf/controller" "state" "beta") $templateDefaults) }}</li>
</ul>
</div>
<div class="product-group">

View File

@ -1,21 +0,0 @@
{{- /* Define more precise regex patterns for each dynamic value type */ -}}
{{- /* Note: markdownify converts & to &amp; so we need to match that */ -}}
{{- $paramsRegex := `&amp;\{[^}]+\}` -}}
{{- $envsRegex := `\$\{[^}]+\}` -}}
{{- $secretsRegex := `@\{[^:]+:[^}]+\}` -}}
{{- /* Get the inner content and markdownify it */ -}}
{{- $code := .Inner | markdownify -}}
{{- /* Apply replacements for each type of dynamic value */ -}}
{{- /* Replace parameters with span class="param" */ -}}
{{- $code = replaceRE $paramsRegex `<span class="tc-dynamic-value param">$0</span>` $code -}}
{{- /* Replace environment variables with span class="env" */ -}}
{{- $code = replaceRE $envsRegex `<span class="tc-dynamic-value env">$0</span>` $code -}}
{{- /* Replace secrets with span class="secret" */ -}}
{{- $code = replaceRE $secretsRegex `<span class="tc-dynamic-value secret">$0</span>` $code -}}
{{- /* Output the processed code */ -}}
{{ $code | safeHTML }}

View File

@ -0,0 +1,37 @@
{{/*
tc-downloads shortcode
Renders a gated download experience for Telegraf Controller.
- Shows a "Download" button that opens a contact form modal.
- After form submission (or email link with ?ref=tc), JS renders
download links from the JSON data attribute.
- Data sourced from data/tc_downloads.yml (metadata only — URLs are
constructed here at build time).
*/}}
{{- $data := .Site.Data.tc_downloads -}}
{{- $baseURL := "https://telegraf-controller-artifacts.s3.us-east-1.amazonaws.com" -}}
{{- $version := $data.version -}}
{{/* Build enriched platform data with constructed URLs */}}
{{- $platforms := slice -}}
{{- range $data.platforms -}}
{{- $builds := slice -}}
{{- range .builds -}}
{{- $ext := .ext | default "" -}}
{{- $filename := printf "telegraf_controller-%s-%s%s" .os .arch $ext -}}
{{- $url := printf "%s/v%s/%s" $baseURL $version $filename -}}
{{- $build := dict "arch" .arch "os" .os "sha256" .sha256 "filename" $filename "url" $url -}}
{{- $builds = $builds | append $build -}}
{{- end -}}
{{- $platforms = $platforms | append (dict "name" .name "builds" $builds) -}}
{{- end -}}
{{- $enriched := dict "version" $version "platforms" $platforms -}}
<div id="tc-downloads-area">
<a class="btn" id="tc-download-btn"
onclick="window.influxdatadocs.toggleModal('#tc-downloads')">
Download Telegraf Controller
</a>
<div id="tc-downloads-links" style="display: none;"
data-downloads="{{ $enriched | jsonify | base64Encode }}">
</div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB