# API Keys Source: https://docs.bronto.io/Account-Management/API-Keys Create, manage, and rotate Bronto API keys to authenticate integrations and route telemetry to the correct service in your organization. ## Manage API Keys Navigate to the the `Settings > API Keys` item from the application sidebar to manage your API Keys. Api Key Manage Pn ## Create a new API Key ## API Key Roles Bronto allows users to specificy roles in order to limit what resources an api key can access. We currently provide the following roles: | Role Name | Description | Required for following features | | - | - | - | | Admin | Access to all read write permissions on an account | Creating API Keys | | Search | Read permissions for an accounts data | Interacting with [REST API](/api-reference/introduction) | | Ingestion | Used for writing and sending data to a service in your account | Data ingestion | ## Best practices * Create a separate API key for each service that sends data to Bronto. * Give each key the least-privileged role it needs. Services that only send data need the Ingestion role. * Never embed API keys in client-side code, such as browser or mobile apps, and don't share keys between teams. * Rotate keys on a schedule, and rotate a key at once if you suspect it has been exposed. To rotate a key, create a new key, update the service to use it, then delete the old key. * Delete keys that are no longer in use. ## Edit API Keys * Within the API Key page, hover over a key you wish to edit, click pencil icon that appears on the right side * Here you can edit the roles assocaited with the key and the key name * Under Permissions we list the various part of the product this given key can interact with ## Deleting API Keys * Within the API Key page hover over a key you wish to permenantly delete * Select the trash icon to delete * **Note:** Deleting a key will permanently impact any services currently using it and revoke any access where it is being used. # Access Control Source: https://docs.bronto.io/Account-Management/Access-Control Bronto offers a flexible access management system that allows you to customize the level at which you control access to your Bronto resources. ## Role Based Access Control Roles categorize users and define what account permissions those users have, such as what data they can read or what account assets they can modify. By default, Bronto offers three roles. | Role Name | | Description | | - | - | - | | Administrator | | The Administrator Role grants individuals full access and control over the application. | | Standard | | The standard role grants full access over all non sensitive areas of the application. | | Read-Only | | The read only role grants read access to non sensitive areas of the application. | ## Custom Roles Create custom roles to combine multiple permissions into new, tailored roles. A custom role allows you to assign various CRUD permissions across Access Management, API Key Management, Billing and Usage, Dashboards, Integrations, Limits, Log Management, Monitors, and Tags Management. Once a role is created, you can assign or remove permissions directly by updating the role in the Organization Roles Settings page. Roles Pn You can assign granular permissions across: * Access Management * API Key Management * Billing & Usage * Dashboards * Integrations * Limits * Log Management * Monitors * Tag Management You can manage roles in **Organization Settings → Roles**. #### Note: Permissions for roles in Bronto are additive — if a user is assigned multiple roles, they receive the union of all permissions from those roles. For example, if one role grants permission to create monitors and another does not, the user will still be allowed to create monitors. However, for dataset access permissions, **denials take precedence**: if a dataset or collection is explicitly forbidden, access will be denied even if another role permits it. *** ## Fine-Grained Access with Dataset Restrictions Bronto supports access restrictions for datasets and collections. These allow you to: * Restrict a role to **only access datasets or collections** * Deny access to specific datasets or collections (even if the role has general read permissions) ### Example Use Cases * A security team role that only provides access to the `security` collection * An external auditor role that cannot access PII-related datasets *** ## Best Practices * Use built-in roles for general access and admin controls. * Use custom roles to create scoped access patterns (e.g., Billing-only, Security-only). * Always test new roles with limited users before broad rollout. *** # Bring Your Own Key (BYOK) Source: https://docs.bronto.io/Account-Management/BYOK Encrypt Bronto data at rest using your own AWS KMS customer-managed key (BYOK) for tighter compliance, key rotation, and access control. ## Overview Bronto supports **Bring Your Own Key (BYOK)** for **encryption at rest**. When enabled, Bronto encrypts your data using **your own AWS KMS key**, giving you full control over key ownership, lifecycle, and access. Bronto **never stores or manages your encryption key material**. When BYOK is enabled: * Newly ingested data stored in Bronto is encrypted at rest. * You retain full control over key rotation, disablement, and deletion. ## Enabling Encryption Keys Encryption keys are an **enterprise feature** and must be enabled by **Bronto Support**. Once enabled, an **Encryption Keys** section becomes available in your organization settings. ## Creating the key in AWS ### 1) Create a customer-managed KMS key 1. Open **AWS Console → Key Management Service (KMS)** 2. Go to **Customer managed keys** 3. Click **Create key** 4. Choose: * **Key type:** Symmetric * **Key usage:** Encrypt and decrypt * **Region:** **Multi-Region key (Mandatory)** 5. Click **Next** ### 2) Set alias and rotation 1. Choose a key alias, for example: * `alias/bronto-archive-prod` 2. (Recommended) Enable **automatic key rotation** 3. Click **Next** ### 3) Set key administrators 1. Select your internal AWS admins or security team 2. These users can **rotate, disable, or delete** the key 3. Click **Next** ### 4) Set the key policy (Required) Replace the default policy with the following customer key policy **(or add the second statement to the default)**. This policy: * Keeps full control with your AWS account root * Allows Bronto to use the key only for encryption and decryption ```json theme={"dark"} { "Version": "2012-10-17", "Id": "key-consolepolicy-3", "Statement": [ { "Sid": "EnableIAMUserPermissions", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::xxx:root" }, "Action": "kms:*", "Resource": "*" }, { "Sid": "AllowBrontoKmsUsage", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::637423326566:role/BrontoByok" }, "Action": [ "kms:Encrypt", "kms:Decrypt", "kms:GenerateDataKey", "kms:DescribeKey" ], "Resource": "*" } ] } ``` ### 5) Copy the KMS Alias ARN After creation: 1. Open the key in **KMS** 2. Go to the **Aliases** tab 3. Copy the **alias ARN**, for example: ```text theme={"dark"} arn:aws:kms:eu-west-1:026090548703:alias/bronto-archive-prod ``` ## Adding an Encryption Key in Bronto To add a key once enabled on your account: 1. Go to **Settings → Encryption Keys** 2. Click **Add Encryption Key** 3. Enter: * **Display Name (optional)** — for identification inside Bronto * **AWS KMS Alias ARN** — the alias ARN of the KMS key you created in AWS 4. Click **Create** The key will not be used until it has been activated and Bronto begins storing data for the organization. *** ## Activating the Key To enable encryption at rest: 1. Open the key 2. Click **Activate Key** 3. Confirm the warning Once activated: * All newly ingested data is encrypted using this key. * The **Last used** date of the key will indicate when this is working. * The key **cannot be deactivated or replaced via the UI**. * Reversal requires contacting **Bronto Support**. * This action is intentional and treated as **permanent**. *** ## Important warnings

Bronto has no control over your KMS key.

# Multi-Organisation Source: https://docs.bronto.io/Account-Management/Multi-Org Operate multiple independent organisations within a single Bronto account, with centralised governance, role-based access, and isolated data. This guide covers: * What multi-organisation support does (and does not do) * How to enable it * How access works with users and groups ## 1. What Multi-Organisation Support Does When enabled, multi-organisation support allows you to: * Create separate organisations under a single parent (management) organisation * Assign users or groups to each organisation with specific roles * Cleanly isolate data, dashboards, monitors, and integrations between organisations * Switch between organisations using a selector in the interface Each organisation functions as an independent workspace, while the management organisation retains control over access and configuration. ## 2. What Multi-Organisation Support Does Not Do To avoid confusion, multi-organisation support has the following limitations: * You **cannot query multiple organisations at the same time** * All searches, dashboards, monitors, and API requests operate only on the **currently selected organisation** * There is **no cross-organisation aggregation**, federated querying, or unified analytics view * Switching organisations fully changes context, including: * Data * Dashboards * Monitors * Integrations * Usage ## 3. Enabling Multi-Organisation Mode To enable multi-organisation support: 1. Go to **Settings → Organisations** 2. Open the **General** tab General organisation settings 3. Toggle **Multi-Organisation Setup** to enable it You will then see two additional options: Multi-organisation options ### Create New Management Organisation * Creates a new, empty parent (management) organisation * If **disabled**, your current organisation becomes the management organisation * If **enabled**, you will be prompted to provide a name for the new management organisation Create management organisation ### Grant All Users Access * Retains access for all existing users after migration * If disabled, only you (the administrator) retain access initially * This operation **cannot be undone** without contacting support > **Note:**\ > The administrator who enables multi-organisation support is automatically added as an **Admin** to: > > * The management organisation > * Any newly created child organisations ### Sign-in Required After enabling multi-organisation support, **log out and back in** to refresh your session. ## 4. The Organisation Switcher After signing back in, an organisation selector appears in the **top-left of the navigation menu**. This dropdown shows every organisation you have access to. Selecting an organisation switches your entire Bronto workspace to that context. Organisation switcher > **Note:**\ > The management organisation is denoted by a **crown icon**. ## 5. Groups: Managing Access at Scale Groups simplify managing access across multiple organisations. A **group** is a platform-level collection of users that can be granted roles on one or more organisations. ### Creating a Group 1. Go to **Settings → Groups** 2. Click **Create Group** and provide a name 3. Open the group and add users using the **Edit** button Groups are: * Global across the platform * Visible and manageable **only from the management organisation** ## 6. Assigning Users and Groups to Organisations To manage organisation access: 1. Go to **Settings → Organisations** 2. Select an organisation 3. Click **Edit Organisation** You can then: * Add users directly * Add groups * Assign roles to each (e.g. **Viewer**, **Editor**, **Admin**) ### Group Access Behaviour When adding a group: * All users in the group automatically gain access * Permissions are determined by the role assigned to the group * Access persists until: * The user is removed from the group, or * The group’s organisation assignment is changed > **Roles are additive**\ > A user’s effective permissions are the combined permissions from all roles they hold across direct and group assignments. ## 7. Notes and Behaviour * **Groups** and **Organisations** settings are only available in the **management organisation** * Users can belong to multiple organisations with different roles in each * Removing a user from a group immediately removes their inherited organisation access * Child organisations **cannot** create or modify groups # Data Retention Source: https://docs.bronto.io/Account-Management/Retention Configure how long Bronto retains your data at the organisation and dataset level to control storage costs and meet compliance requirements. ## Overview Bronto lets you control how long your data is stored — both as a global default across your organisation and as custom overrides per dataset. Data marked for deletion will enter a grace period and remains queryable before expiration. ## Organisation Policy The **Organisation Policy** sets the default retention period applied to all datasets that don't have a custom override. Your plan determines the maximum retention available. To update the default: 1. Go to **Settings → Plan → Retention**. 2. Under **Organization Policy**, select a retention period from the **Default Retention** dropdown. 3. Click **Save Default**. Available retention periods are **30 days**, **90 days**, **180 days**, and **365 days**, up to your plan maximum. ## Custom Retention Overrides You can override the default retention for individual datasets — useful when certain data needs to be kept longer or can be discarded sooner. To apply a custom override: 1. Under **Filter Datasets**, search for the dataset you want to configure. 2. Select it — it will appear as a **Dataset Rule** tag. 3. Choose a retention period from the **Set retention...** dropdown. 4. Click **Save**. The dataset will move from **Using Default Retention** into the **Custom Retention Overrides** list, showing its specific policy. To remove a custom override and revert a dataset to the organisation default, clear the rule from the Custom Retention Overrides list. ## Viewing Retention by Dataset The right panel shows all datasets grouped by their retention status: * **Custom Retention Overrides** — datasets with a specific retention rule applied, and the count of datasets affected. * **Using Default Retention** — all remaining datasets inheriting the organisation default. Expand any namespace to see the individual datasets within it. # SSO Overview Source: https://docs.bronto.io/Account-Management/SSO/SSO-Overview Configure single sign-on (SSO) so users log in to Bronto through your identity provider using SAML or OIDC, instead of a password. ## Overview Single sign-on (SSO) lets your users log in to Bronto through your existing identity provider (IdP) instead of a Bronto password. Bronto supports both **SAML** and **OIDC** providers. For step-by-step instructions for a specific provider, see: * [Google SAML IdP](/Account-Management/SSO/google-saml) * [Okta OIDC](/Account-Management/SSO/okta-oidc) * [Microsoft Entra ID](/Account-Management/SSO/entra-id) (SAML or OIDC) ## Add an identity provider 1. In Bronto, go to **Settings** > **Authentication** > **Login Methods**. 2. In the **SSO** section, click **Add Provider** to launch the setup wizard. Authentication Login Methods with the SSO provider list At the top of the wizard, set **Choose protocol** to **SAML** or **OIDC**. The wizard then has four steps: **Name**, **Upload** (SAML) or **Provide** (OIDC), **Email**, and **Map**. Choose protocol — SAML or OIDC ### Name Pick a unique name for this IdP within your organisation. ### Upload (SAML) / Provide (OIDC) Provide the connection details for your chosen provider: * **SAML** — Upload the IdP metadata XML from your provider. * **OIDC** — Enter the **Client ID**, **Client Secret**, and **Issuer URL** from your provider. The **Paste these into your IdP** panel shows the values you need to configure on the provider side — for SAML the **ACS URL**, **Entity ID**, and **Default Relay State**; for OIDC the **Redirect URI** and **Start URL**. See your IdP-specific documentation for where to enter them. ### Email Choose the email domains associated with this IdP. They are used to recognise which IdP to use for a given account, and the field is prepopulated with your organisation's email domain. Type a domain and press **Enter** to add it. Each domain may only be associated with a single IdP — ensure they do not repeat across providers. ### Map Map your IdP's attributes to Bronto's. The attributes required by Bronto are **First Name**, **Last Name**, and **Email**. Input the matching provider attribute name, as configured in your IdP, in each row (e.g. `given_name` → First Name). If you wish to use [role mapping](/Account-Management/SSO/SSO-Role-Mapping), also add a mapping to the **custom:member\_of** attribute — click **+ Add role mapping** if a row for it isn't already shown. Click **Save** to create and enable the IdP. ## Manage providers Your new IdP is enabled automatically and appears in the **SSO** list on the **Login Methods** page, where you can enable or disable it, view its details, edit it, or delete it. You control which login methods are enabled from the same page — you must always have at least one login method enabled. If your organisation sends telemetry from a PCI DSS environment, Bronto strongly recommends disabling password login to meet PCI DSS v4.0.1 requirements. Disable it after you confirm that SSO sign-in works, so every user signs in through your identity provider and its MFA. To view a provider's connection details again (ACS URL, Entity ID, Start URL, etc.), open the provider from the **SSO** list. ## Next steps If you wish to use role mapping, configure it on the **SAML Role Mappings** tab. See [SSO Role Mapping](/Account-Management/SSO/SSO-Role-Mapping) for more information. # SSO Role Mapping Source: https://docs.bronto.io/Account-Management/SSO/SSO-Role-Mapping Map SAML attributes from your identity provider to Bronto user roles so user permissions are provisioned automatically from your IdP. ## Prerequisites In order to set up role mapping, you must first create an attribute mapping to **custom:member\_of** in at least one of your IdPs. This can be done when creating a new IdP or by editing an existing one. Go to the [SSO Overview](/Account-Management/SSO/SSO-Overview) for more information on creating an IdP. ## Map SAML attributes to Bronto Roles 1. Go to **Settings**, open **Authentication**, and click the **SAML Role Mappings** tab. **NOTE:** If the role mappings list is not visible, you likely don't have the **custom:member\_of** attribute mapping configured in your IdPs. Verify this is configured, and contact support in case of any issues. 1. Click the **+ New Mapping** button in the top right corner to begin creating new role mappings. A popup should appear. 2. In the popup, fill in the possible value of the **custom:member\_of** attribute and the appropriate Bronto role from the dropdown. Each user with a matching value, will be given the corresponding role. 3. If you wish, you can use the **add new row** button to configure multiple mappings in one go. 4. Press **Create** to create and enable the mappings. 5. If you wish to edit an existing mapping, hover over it in the list and press the pencil(**Edit**) button. If you configure multiple mappings with the same value, only the latest one will be in effect. When a user with a specified identity provider attribute logs in, they will be given the appropriate Bronto role. Likewise if the attribute is removed, their role will also be removed. If a user doesn't match any attribute mappings, they will be given the **Standard** role by default. Map every identity provider group that signs in to Bronto to a role explicitly, so no user falls through to the Standard role unintentionally. Give each group the least-privileged role it needs, which can be a custom role you've created. PCI DSS v4.0.1 expects access to be deny-by-default, and the Standard role still grants access to non-sensitive areas. # Microsoft Entra ID Source: https://docs.bronto.io/Account-Management/SSO/entra-id Configure Microsoft Entra ID (formerly Azure AD) as a SAML or OIDC single sign-on provider for Bronto, and map Entra ID groups to Bronto roles. ## Overview Microsoft Entra ID can be configured as an identity provider for Bronto using either **SAML** or **OIDC**. Both options let your users sign in to Bronto with their existing Microsoft credentials, and both support [role mapping](/Account-Management/SSO/SSO-Role-Mapping) so Bronto permissions are provisioned automatically from your Entra ID group membership. Choose the option that matches your organization's preference: * **SAML** — Configure Bronto as a SAML application in Entra ID. Best if your organization standardizes on SAML for enterprise apps. * **OIDC** — Register Bronto as an app registration and authenticate through OpenID Connect. Before you begin you need a Microsoft Entra ID tenant and an account with the **Global Administrator**, **Cloud Application Administrator**, or **Application Administrator** role. For Microsoft's own reference, see [Microsoft Entra ID documentation](https://learn.microsoft.com/en-us/entra/identity/). If you intend to use role mapping, first create an attribute mapping to **custom:member\_of** when configuring the IdP in Bronto. See [SSO Role Mapping](/Account-Management/SSO/SSO-Role-Mapping). ## Manage SSO providers in Bronto You configure and manage identity providers from **Settings** > **Authentication** > **Login Methods**. The **SSO** section lists your existing SAML and OIDC providers and lets you add new ones. Each provider row shows its type (SAML or OIDC), associated email domains, user count, and last login, with controls to enable/disable, view details, edit, or delete it. Click **Add Provider** to launch the setup wizard. On the first step you set **Choose protocol** to **SAML** or **OIDC**; the wizard then has four steps — **Name**, **Upload** (SAML) or **Provide** (OIDC), **Email**, and **Map**. ## SAML authentication ### Step 1: Create the Enterprise Application in Entra ID 1. Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com). 2. Navigate to **Identity** > **Applications** > **Enterprise applications**. 3. Click **New application**, then **Create your own application**. 4. Enter a name (e.g. "Bronto"), select **Integrate any other application you don't find in the gallery (Non-gallery)**, and click **Create**. See Microsoft's [Add an enterprise application](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/add-application-portal) and [Configure SAML-based single sign-on](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/add-application-portal-setup-sso) for full details. ### Step 2: Configure SAML in Entra ID 1. In the new application, open **Single sign-on** and select **SAML**. 2. Edit the **Basic SAML Configuration** and enter the following values from Bronto. They appear in the **Paste these into your IdP** panel on the **Upload** step of the Bronto wizard (see Step 4), and again whenever you open the provider from the **SSO** list: * **Identifier (Entity ID)** — Use the **Entity ID** from Bronto. * **Reply URL (Assertion Consumer Service URL)** — Use the **ACS URL** from Bronto. * **Relay State** — Use the **Default Relay State** from Bronto. 3. Click **Save**. ### Step 3: Configure attributes and claims Bronto requires **First name**, **Last name**, and **Email** attributes. In **Attributes & Claims**, map the Entra ID source attributes to the attribute names you configured when creating the IdP in Bronto. Entra ID's defaults are: | Bronto attribute | Entra ID source attribute | | - | - | | First name | `user.givenname` | | Last name | `user.surname` | | Email | `user.mail` | To use role mapping, add a **group claim** that emits group membership and map it to the attribute mapped to **custom:member\_of** in Bronto: 1. In **Attributes & Claims**, click **Add a group claim**. 2. Select which groups to emit (e.g. **Groups assigned to the application**). 3. Under **Source attribute**, choose **Group ID**. Bronto matches role mappings on the group's **Object ID** (a GUID in the form `00000000-0000-0000-0000-000000000000`), so the claim must emit group IDs rather than display names. 4. Set the claim name to match the source attribute you mapped to **custom:member\_of** in Bronto. For details, see Microsoft's [Configure group claims for applications](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-fed-group-claims). Then see [Map Entra ID groups to Bronto roles](#map-entra-id-groups-to-bronto-roles) below. ### Step 4: Configure the IdP in Bronto 1. In Entra ID, download the **Federation Metadata XML** from the **SAML Certificates** section. 2. In Bronto, go to **Settings** > **Authentication** > **Login Methods** and click **Add Provider** in the **SSO** section. 3. Work through the wizard: * **Name** — Give the provider a unique name and set **Choose protocol** to **SAML**. * **Upload** — Upload the Federation Metadata XML. The **Paste these into your IdP** panel shows the **ACS URL**, **Entity ID**, and **Default Relay State** to configure on the Entra ID side (Step 2). * **Email** — Add the email domains to route to this provider. * **Map** — Map your IdP attributes to Bronto's required **First Name**, **Last Name**, and **Email**. To use role mapping, click **+ Add role mapping** and map your group claim to **custom:member\_of**. 4. Click **Save** to create and enable the IdP. ### Step 5: Assign users or groups 1. In the Enterprise Application, go to **Users and groups**. 2. Click **Add user/group** and select the users or security groups who should have access to Bronto. 3. Click **Assign**. Assigning a security group is recommended over individual users for easier ongoing access management. ## OIDC authentication ### Step 1: Register the application in Entra ID 1. Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com). 2. Navigate to **Identity** > **Applications** > **App registrations** and click **New registration**. 3. Enter a name (e.g. "Bronto"). 4. Under **Redirect URI**, select **Web** and enter the URI for your Bronto region: * **EU:** `https://auth.eu.bronto.io/oauth2/idpresponse` * **US:** `https://auth.us.bronto.io/oauth2/idpresponse` 5. Click **Register**. 6. From the app **Overview**, note the **Application (client) ID** and your **Directory (tenant) ID**. 7. Go to **Certificates & secrets**, create a **New client secret**, and note its value. See Microsoft's [Register an application with the Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app) for full details. ### Step 2: Configure SSO in Bronto In Bronto, go to **Settings** > **Authentication** > **Login Methods**, click **Add Provider** in the **SSO** section, and work through the four steps of the wizard. #### Name Enter a unique **Provider name** for this IdP within your organisation (e.g. "EntraIDtest") and select **OIDC** as the **Identity Provider type**. #### Provide The **Paste these into your IdP** panel on the right shows the values Bronto generates for your account and region. Use these in your Entra ID app registration first: * **Redirect URI** — e.g. `https://auth.eu.bronto.io/oauth2/idpresponse` (or `auth.us.bronto.io` for US). This matches the Redirect URI you set in Step 1. * **Start URL** — used for IdP-initiated sign-in. Then paste your Entra ID values into the fields on the left: * **Client ID** (from Step 1) * **Client Secret** (from Step 1) * **Issuer URL:** `https://login.microsoftonline.com//v2.0`, where `` is your **Directory (tenant) ID** from Step 1. #### Email Add the email domains that should route to this provider (e.g. `contoso.com`, `contoso.onmicrosoft.com`). Type each domain and press **Enter**. #### Map Tell Bronto where to find each user attribute in the OIDC payload. Entra ID's defaults are: | IdP attribute | Bronto attribute | | - | - | | `email` | Email *(required)* | | `family_name` | Last Name *(required)* | | `given_name` | First Name *(required)* | | `groups` | `custom:member_of` *(for role mapping)* | | `sub` | — | To use role mapping, add a row mapping the **`groups`** IdP attribute to **`custom:member_of`**. Click **Save** to create and enable the IdP. ### Step 3: Configure the Homepage URL for IDP-initiated login (optional) To launch Bronto directly from the Microsoft My Apps portal, set the application's Homepage URL to the IDP-initiated login URL: 1. In the [Microsoft Entra admin center](https://entra.microsoft.com), open the linked **Enterprise Application** for your app registration (from the app **Overview**, click the link next to **Managed application in local directory**). 2. Go to **Properties** and paste the Start URL from Bronto (or an equivalent constructed login URL) into the **Homepage URL** field. 3. Set **Enabled for users to sign-in?** and **Visible to users?** to **Yes**, then click **Save**. My Apps can take up to 10 minutes to reflect changes after setup. If the tile does not appear immediately, wait a few minutes and hard-refresh the page. ## Map Entra ID groups to Bronto roles Role mapping uses the **custom:member\_of** attribute. When you emit Entra ID group membership into that attribute (a group claim for SAML, or the groups claim for OIDC), Bronto matches each group value to a Bronto role. Bronto matches on the Entra ID group's **Object ID** — the GUID assigned to the group in Entra ID, not its display name. You can find a group's Object ID in the [Microsoft Entra admin center](https://entra.microsoft.com) under **Identity** > **Groups** > select the group > **Overview**. 1. Ensure the **custom:member\_of** attribute mapping is configured for your Entra ID IdP, and that Entra ID emits group **Object IDs** into it (see Step 3 of SAML, or Step 2 of OIDC above). 2. In Bronto, go to **Settings** > **Authentication** > **SAML Role Mappings**. 3. Click **+ New Mapping** and create a mapping for each group, selecting the Bronto **Role** and entering the group's Object ID as the **Provider Value** (the **Provider Key** is `custom:member_of`). For example, to grant the Administrator role to a group, set the **Provider Value** to that group's Object ID (a GUID in the form `00000000-0000-0000-0000-000000000000`) and select **Administrator Role**. For full details on creating and editing mappings, see [SSO Role Mapping](/Account-Management/SSO/SSO-Role-Mapping). If a user doesn't match any role mapping, they will be given the **Standard** role by default. ## Troubleshooting * **Authentication fails:** Verify the Client ID and Client Secret (OIDC) or the Entity ID, ACS URL, and certificate (SAML) are correct. * **Redirect errors:** Ensure the redirect URI exactly matches the region-specific value configured in Entra ID. * **User cannot access the application:** Check user and group assignments in the Enterprise Application. * **Missing user information:** Verify attribute mapping in both Entra ID and Bronto. * **Roles not applied:** Confirm the group claim emits group **Object IDs** and is mapped to **custom:member\_of**, and that matching Object IDs exist as the **Provider Value** in **SAML Role Mappings**. * **"Need admin approval":** An administrator must grant consent for the app in **Enterprise Application** > **Permissions** > **Grant admin consent**. For questions about your Bronto SSO parameters or configuration, contact [support@bronto.io](mailto:support@bronto.io). # Google SAML IdP Source: https://docs.bronto.io/Account-Management/SSO/google-saml Configure Google Workspace as a SAML identity provider for Bronto so users can sign in with their existing Google accounts via single sign-on. Configure Google Workspace as a SAML identity provider so your users can sign in to Bronto with their existing Google accounts. You start the provider in Bronto to obtain the values to paste into Google, configure the Google SAML app, then finish the Bronto wizard. ## Step 1: Start the provider in Bronto In Bronto, go to **Settings** > **Authentication** > **Login Methods** and click **Add Provider** in the **SSO** section. Set **Choose protocol** to **SAML**. ### Name Pick a unique name for this IdP within your organisation (e.g. "Google"). Name your provider step ### Upload On the **Upload** step, the **Paste these into your IdP** panel shows the values you need to configure the Google SAML app — the **ACS URL**, **Entity ID**, and **Default Relay State**. Keep this open while you configure Google in Step 2, then upload the metadata XML that Google gives you back into this step. Upload IdP metadata step ## Step 2: Configure the SAML app in Google [View the dedicated Google instructions](https://support.google.com/a/answer/6087519?hl=en#zippy=%2Cstep-add-the-custom-saml-app) ### Service Provider Details * **Application Name -** Can be anything * **Description -** Can be anything * **ACS URL -** Use the **ACS URL** from the Bronto **Upload** step. * **Entity ID -** Use the **Entity ID** from the Bronto **Upload** step. * **Start URL -** Use the **Default Relay State** from the Bronto **Upload** step. * **Signed Response -** Leave unchecked * **Name ID -** Select **Basic Information** and **Primary Email** ### Attribute Mapping Bronto requires a First name, Last name and Primary Email attributes from Basic Information. These can map to any fields, as long as you match the names used when configuring the IdP in Bronto. If you wish to use role mapping, you must also configure attribute mapping from group membership to the attribute mapped to **custom:member\_of**. See [SSO Role Mapping](/Account-Management/SSO/SSO-Role-Mapping). ## Step 3: Finish the wizard in Bronto Back in Bronto, upload the metadata XML from Google on the **Upload** step, then complete the remaining steps. ### Email Add the email domains that should route to this provider (e.g. `bronto.io`). Type each domain and press **Enter**. Email domains step ### Map Map your Google attributes to Bronto's required **First Name**, **Last Name**, and **Email**, matching the attribute names you configured in Google. To use role mapping, click **+ Add role mapping** and map your group membership attribute to **custom:member\_of**. Map IdP attributes step Click **Save** to create and enable the IdP. # Okta OIDC Source: https://docs.bronto.io/Account-Management/SSO/okta-oidc Configure Okta as an OIDC single sign-on provider for Bronto so users authenticate through your existing identity provider with centralised access. ## Overview OpenID Connect (OIDC) Single Sign-On allows your organization to manage authentication through your existing identity provider. This integration streamlines user access, enhances security, and simplifies user management across your organization. This page covers configuring Okta as an OIDC provider; for other providers see the [SSO Overview](/Account-Management/SSO/SSO-Overview). ### Step 1: Create an OIDC Application in Okta See Okta's [Create OIDC app integrations](https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_oidc.htm) for full details. 1. Sign in to your Okta Admin Dashboard 2. Navigate to **Applications** > **Applications** 3. Click **Create App Integration** 4. Select **OIDC - OpenID Connect** as the Sign-in method 5. Choose **Web Application** as the Application type 6. Click **Next** 7. Enter an Application name (e.g., "Bronto") 8. Add the following Redirect URI which will depend on your Bronto accounts region: * **EU:** `https://auth.eu.bronto.io/oauth2/idpresponse` * **US:** `https://auth.us.bronto.io/oauth2/idpresponse` 9. Under "Allowed grant types," ensure "Authorization Code" is selected 10. Under "Assignments," select which users or groups should have access 11. Click **Save** 12. Note the **Client ID** and **Client Secret** from the application details ### Step 2: Configure the provider in Bronto Navigate to **Settings** > **Authentication** > **Login Methods** and click **Add Provider** in the **SSO** section. Set **Choose protocol** to **OIDC**, then work through the wizard: 1. **Name** — Pick a unique provider name within your organisation (e.g. "Okta"). 2. **Provide** — Enter the **Client ID** and **Client Secret** from Step 1, and the **Issuer URL** (`https://your-okta-domain.okta.com`). The **Paste these into your IdP** panel shows the **Redirect URI** (which matches the one you set in Step 1) and the **Start URL** — copy the Start URL for Step 3. 3. **Email** — Add the email domains to route to this provider (e.g. `your-company.io`). 4. **Map** — Map Okta's attributes to Bronto's required fields. Okta's defaults are `given_name` (First Name), `family_name` (Last Name), and `email` (Email). To use role mapping, click **+ Add role mapping** and map your group claim to **custom:member\_of**. 5. Click **Save** to create and enable the IdP. ### Step 3: Add the Start URL to Okta 1. Go to the Okta app created above and select **Edit** next to **General Settings**. 2. Paste the **Start URL** from Step 2 into the **Initiate login URI** field and save. 3. Ensure **Login initiated by** is set to **Either Okta or App**. 4. Ensure **Display application icon to users** is enabled. ### Troubleshooting * **Authentication fails:** Verify the Client ID and Client Secret are correct * **Redirect errors:** Ensure the redirect URI exactly matches what's configured in Okta * **User cannot access the application:** Check group assignments in Okta * **Missing user information:** Verify attribute mapping in both Okta and Bronto * **App Missing from Okta panel:** Ensure "Login initiated by" setting is set to "Either Okta or App", is assigned to users and "Application visibility" is set to "Display application icon to users" # Security Source: https://docs.bronto.io/Account-Management/Security Learn how Bronto protects your data with SOC 2 Type II compliance, encryption at rest and in transit, role-based access controls, and audit logging. ## Certifications and Compliance * **SOC 2 Type I and Type II:** Bronto has completed both its SOC 2 Type I and SOC 2 Type II audits, and maintains SOC 2 Type II compliance through recurring audits. Current SOC 2 reports and bridge letters are available on request from the [Bronto Trust Center](https://trust.bronto.io). * **GDPR Compliance:** Ensures the privacy and protection of personal data for customers in the EU, adhering to the General Data Protection Regulation. * **CCPA Compliance:** Guarantees the privacy and protection of personal data for customers in California, in accordance with the California Consumer Privacy Act (CCPA). Requests related to CCPA can be addressed by contacting [support@bronto.io](mailto:support@bronto.io). * **Continuous Compliance Monitoring:** Utilizes advanced tools and systems to continuously monitor compliance with security standards and regulations, promptly addressing any gaps. For the current list of certifications, security controls, audit reports, and sub-processors, see the [Bronto Trust Center](https://trust.bronto.io). ## Comprehensive Security Measures Bronto employs a comprehensive approach to data security, encompassing encryption, penetration testing, system protection, and robust organizational measures. ## Data Encryption At Bronto, data is encrypted both at rest and in transit, adhering to industry standards and undergoing regular audits to ensure maximum security. * **Data at rest** is stored within Amazon Web Services (AWS) infrastructure and secured with AES-256 bit encryption provided by AWS technologies. * **Data in transit** is protected using AES-256 bit encryption and TLS to secure network traffic. ## Data Residency Bronto currently offers two regional environments: one where data is ingested and stored in the EU, and one where data is ingested and stored in the US. You select your region when creating your Bronto account. The EU and US environments are isolated from each other. Data sent to the EU environment remains in EU data centres, and data sent to the US environment remains in US data centres. After selecting a region, configure your agents, collectors, and integrations to send data to the matching Bronto ingestion endpoint. See [Ingestion Endpoints](/getting-started/bronto-endpoints) and [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) for regional endpoint details. ## Penetration Testing Bronto conducts regular vulnerability scans and third-party penetration tests to proactively identify and mitigate potential security threats. The latest penetration test reports are available on request from the [Bronto Trust Center](https://trust.bronto.io). ## System Protection and Resilience Against Failure Bronto systems are segmented into separate networks and protected by restrictive firewalls and Virtual Private Networks (VPNs) to secure network traffic and prevent unauthorized access. Network segmentation isolates sensitive data and systems. Regular backups and tested data recovery procedures ensure business continuity. Additionally, vulnerability assessments and patch management processes are in place to guard against known vulnerabilities. ## Organisational Security Practices Bronto's commitment to security extends beyond technological measures to include comprehensive organizational practices: * **Employee Training:** All employees receive regular training on security best practices, including phishing awareness, data handling procedures, and incident response protocols. * **Stringent Security Requirements:** We enforce stringent security measures such as encrypted storage and two-factor authentication. * **Security Policies:** Our comprehensive and regularly updated policies cover all aspects of data protection and compliance, ensuring robust governance. * **Incident Response:** A thorough response plan is in place for the prompt identification, assessment, mitigation, and remediation of security incidents, with predefined procedures for effective handling. * **Continuous Monitoring:** We utilize Intrusion Detection Systems (IDS) for real-time threat detection and analysis. ## Sub-processors Bronto collaborates with a limited number of trusted sub-processors. For a complete list, see [Sub-processors](https://trust.bronto.io/subprocessors). We regularly review all third parties to ensure they meet our high security standards. ## Report Vulnerabilities Bronto takes all reports seriously and follows a responsible disclosure process. Please submit any vulnerabilities via email to [security@bronto.io](mailto:security@bronto.io). # User Management Source: https://docs.bronto.io/Account-Management/User-Management Invite, edit, and remove users in your Bronto organisation, assign roles, and review access permissions from the Users settings page. From the `Users` page, you can edit the roles of existing users, their name and view what access permissions they currently have. ## Passwords If you don't sign in through SSO, you sign in to Bronto with your email address and a password. A password on its own is the weakest way to sign in. Use [SSO](/Account-Management/SSO/SSO-Overview) with your identity provider enforcing MFA, or add [MFA](#multi-factor-authentication-mfa) to your Bronto login. Administrators choose which login methods are enabled in **Settings** > **Authentication** > **Login Methods**. ### Password requirements Your Bronto password must: * be at least 8 characters long * include at least one uppercase letter, one lowercase letter, one number, and one symbol ### When to change your password If you sign in with a password only, without SSO or MFA: * Change your password periodically. * Change your password straight away if: * you suspect or know that it has been compromised * someone else may have seen it * you signed in on a shared device and are leaving that device If you suspect your password has been compromised, also tell your organisation administrator. To change your password, go to the Settings page from the left sidebar, select Profile, then select the Security tab. ## Multi-Factor Authentication (MFA) Multi-Factor Authentication (MFA) requires a user to present more than one type of verification to authenticate to a system. We support most authenticator apps including Google Authenticator, Microsoft Authenticator, Duo Security and more. * To setup MFA for your login visit the Settings page from the left sidebar * Select Profile, then from under the Security tab select the Password and Authentication option * From here Click Add to be presented with a QR code to scan with your desired Authentication app * Once Scanned, click next and enter the code from your authenticator app and click next. If you sign in through SSO, configure MFA in your identity provider. Each user enables MFA for their own login. Administrators can't require MFA for all users in Bronto. To enforce MFA across your organisation, use [SSO](/Account-Management/SSO/SSO-Overview) with MFA enforced by your identity provider. If your organisation sends telemetry from a PCI DSS environment, Bronto strongly recommends using SSO with MFA enforced by your identity provider, and disabling password login, to meet PCI DSS v4.0.1 requirements. See [Manage providers](/Account-Management/SSO/SSO-Overview#manage-providers). ## Teams It is possible to create teams in Bronto. From within Organisation Settings you will find a Team menu option where you can manage teams and their assigned users. Teams Pn ### Assign Datasets to a Team Once a team is created for your organisation, you can tag a dataset to associate it with a specific team. * Navigate to the Logs page * Highlight a Dataset you wish to associate with a team * Click the "Dataset Settings" option * Fill out the required fields * Save Changes Team Assign Pn ### Monthly Ingestion Limit Bronto allows setting ingestion limits per team. Setting an ingestion limit (in Bytes, GB, TB etc) will restrict the amount of data that can be ingested each month by datasets assigned to a given team. To set a limit, navigate to the team page then select the edit icon next to a team you wish to set a limit for. Team Limits Pn # FAQ Source: https://docs.bronto.io/FAQ Answers to common questions about the Bronto observability platform, including ingestion, retention, querying, integrations, and account configuration. ## Why didn't sending metrics or traces create a dataset? Datasets and collections are for **logs only**. OpenTelemetry metrics sent to `/v1/metrics` appear in the [Metric Explorer](/metrics/explore-metrics), and traces sent to `/v1/traces` appear in [Explore Traces](/tracing/explore-traces). They do not create or appear in datasets or collections, even when the request includes `x-bronto-dataset` or `x-bronto-collection`. `service.name` and `service.namespace` still provide useful service identity on metrics and traces, but their Dataset and Collection mapping applies only to log records. ## Do I need to create a log dataset before sending data? No. When Bronto successfully receives a log event with a dataset and collection name, it creates that log destination automatically if it does not already exist. If you are sending metrics or traces, check the corresponding explorer instead of waiting for a dataset to appear. # My Data Source: https://docs.bronto.io/My-Data/My-Data Manage your Bronto data, review collections and datasets, monitor data quality, and explore ingestion and search usage from the My Data page. Use **My Data** to manage the data in your Bronto account and understand how it is being used. The page combines dataset management, parser visibility, data quality, usage summaries, and usage explorers in one place. From **My Data**, you can: * Review collections and datasets. * Track monthly ingest volume and search quota usage. * Check parser coverage and data quality. * Open the ingestion and search usage explorers. * Create usage alerts for monthly search or ingestion thresholds. ## Collections and datasets The **Collections and Datasets** table lists the data available in your account. Use it to search collections or datasets, inspect volume, see parser assignments, review team and tag metadata, and add new data sources. Top-level summary cards show ingest volume, search quota usage, and data quality. Use the **Explore** actions on the ingest and search cards to open the corresponding usage explorer. ## Usage Dataset Bronto automatically provides a usage dataset for both Search and Ingestion when an account is created, enabling you to monitor key metrics. * Search: Metrics are logged every 2 minutes, capturing usage per dataset and collection. * Ingestion: Metrics are also logged every 2 minutes, tracking ingestion usage per dataset and collection. ## Usage explorers Usage is accessed from **My Data**. Use the ingestion and search explorers to analyze usage patterns, compare datasets and collections, and understand quota consumption. ### Ingestion Explorer The **Ingestion Explorer** shows total ingestion volume, average daily ingestion, and a grouped breakdown over the selected time range. Toggle between **Volume** and **Cost** views, group by dataset, collection, team, or tag, and apply filters to narrow the results. ### Search usage The search usage view helps you understand how search quota is being consumed across datasets, collections, teams, tags, and users. Use it to identify high-volume searches and monitor quota usage during the month. ## Usage alerts From **My Data**, click **Usage Alerts** to view existing alerts or create a new usage alert. Alerts can notify you when monthly search or ingestion usage exceeds a threshold that you define. To create an alert, provide an alert name, description, threshold value, and destination. Bronto can deliver usage alerts to an email address or an existing webhook. ## REST API Use the [Usage API](https://docs.bronto.io/api-reference/usage/get-the-usage-over-a-period-of-time-for-a-log-id) to retrieve usage data for a specific dataset over a defined timeframe. ## Calculations The displayed usage values vary depending on the endpoint and feature. Below are the units of measurement and how they are calculated: * Usage API: Displays data usage in Bytes. * Usage Dataset: Displays data usage in Bytes. * My Data ingest volume: Data usage is calculated in GB (1 GB = 1,000,000,000 Bytes). * My Data usage explorers: Data usage is displayed in GB (1 GB = 1,000,000,000 Bytes). # Dashboards Source: https://docs.bronto.io/Search-and-Visualize/Dashboards Build Bronto dashboards from metrics and other telemetry to visualize application performance, track trends, and share live views with your team. ## Overview Navigate to the Dashboard page in Bronto by clicking on the "Dashboards" item in the application sidebar. Dashboard Pn ## Create a new Dashboard To create a new Dashboard, click on the "New Dashboard" button in the application sidebar. 1. Choose a name for your Dashboard. 2. Once the dashboard is created, click Add Widgets. 3. Choose a visualization type for your metric (e.g. Bar, Line, Area, Query Value, Top List, or Tree Map). 4. Select the data you want to associate with the widget. For a metric query, select the metric and aggregation function. 5. Apply a filter. For more details, see the [Search Syntax help page](/query-syntax/search-syntax). 6. Lastly, give the widget a title and select Save. Save up to 50 widgets per dashboard. Dashboard Create Pn ## Add Queries and Formulas to Widgets Use **+ Add Query** and **+ Add Formula** to build a widget from more than one query result. Each query has a name, such as `bytes` or `events`, which you can reference in a formula. ### Add a Query Select **+ Add Query** to add another independently configured query to the widget. The new query can use a different scope, filter, aggregation, or grouping from the first query. For Sum, Summary, and Histogram metrics, select **Rate of sum** to display the sum of metric values per second, or **Rate of count** to display the number of observations or metric points per second. For details and examples, see [Aggregation functions](/metrics/explore-metrics#aggregation-functions). For example, to prepare a widget that visualizes the average number of bytes per event: 1. Configure query `bytes` to return the sum of `bytes_total`. 2. Select **+ Add Query**. 3. Configure query `events` to return the sum of `event_count`. The widget now has the total bytes in `bytes` and the total event count in `events`. ### Add a Formula Select **+ Add Formula** to calculate a value from numbers, query results, or a combination of both. Reference a query by entering its query name in the formula. Formulas support: * Parentheses: `(` and `)` * Addition, subtraction, multiplication, and division: `+`, `-`, `*`, and `/` * Numerical constants, including decimals, such as `100`, `5`, or `1.5` * Variables that match the names of queries in the widget Variable names must be alphanumeric and start with a letter. Only variables based on query names in the widget are allowed. You can reference any number of variables in a formula, and each widget can include up to six queries. You can also use `+` and `-` as unary operators to explicitly set the sign of a value. For example, `bytes + -5`, `-events + 1000`, and `bytes + +events` are valid formulas. Continuing the bytes-per-event example: 1. Select **+ Add Formula**. 2. Enter `bytes / events` to divide the total bytes by the total event count. 3. Select a visualization type and save the widget. The widget displays the average number of bytes per event. ## Normalize series For line, area, and other time series widgets with at least three queries, use the **Normalize** toggle to compare trends across series with different magnitudes. Normalization scales each series in the selected time range from its own minimum and maximum values into a `0`-to-`1` range. Normalization affects how the widget is displayed. It does not change the underlying query, metric, formula, or raw values. Use it when the shape of each series matters more than comparing absolute values, such as comparing request volume and latency trends on the same chart. When comparing two queries, Bronto uses a dual-axis chart automatically if each series has a different unit selected. Units do not affect normalization results, but they do format the values displayed in tooltips. ## AI Widget Creator Bronto includes an AI assistant that can create dashboard widgets for you from a plain English prompt. This removes the need to manually configure datasets, aggregations, filters, and visualization types — useful when you're unfamiliar with the underlying data. ### How to use it 1. Open an existing dashboard and click **Add Widget**. 2. At the top of the widget creation form, enter a prompt describing what you want to see. For example: *"show me the errors in my data in the last hour"*. 3. The AI will automatically populate the form fields below — dataset selection, visualization type, aggregation, filters, and widget name. 4. The preview updates instantly so you can see the result before saving. 5. If the output looks right, click **Save**. If not, adjust the form fields manually or send a follow-up prompt to refine it further. ### Real-time feedback As soon as you submit a prompt you'll see live status updates showing what the AI is doing — loading context, processing your request, validating the widget — before it replies with an explanation of what it created. ### Iterating on a widget If the first result isn't quite right you have two options: * **Manually adjust** the form fields directly. * **Continue the conversation** by sending a follow-up prompt with more context. The assistant retains the session so it understands your previous messages. ## Visualization Types Visualization types are the various charts you can include in your widget to display your data. ### **Bar Graph** A bar graph is a visual representation of data that helps analyze and interpret the frequency, volume, or other metrics associated with your data. Example usages include showing error frequency over time, log volume by source, and request counts by status code. ### **Line Graph** A line graph is a graphical representation of information that changes over a period of time. It is a chart made by joining points using line segments. Line graphs are particularly effective for showing trends and patterns over a continuous period. They are ideal for understanding how metrics change over time. Example usage includes error rates over time, throughput over time, and displaying response times. ### **Area Graph** An Area Graph is a visual representation of data that utilizes both lines and filled areas to convey information over a period of time. This type of chart is particularly effective in showcasing data trends and variations over a specified period or across different categories. ### **Query Value** This widget can display the latest value from your various search queries across a specific time window. ### **Top List** The top list visualization enables you to display a list of search values with the most or least of any metric or event value. Examples include graphing CPU usage, disk space, or costs of particular services. ### **Tree Map** Tree maps are used to represent hierarchical data as nested rectangles. They help in understanding the structure and distribution of data within a hierarchy. Examples include log volume by source and type, error distribution across services, resource allocation, and other hierarchical metrics. ### **Percentiles** Analyze your data with percentile views, including P75, P90, P95, and P99, for deeper insights into performance and trends. ## **Full-Screen Mode** In full-screen widget mode, when using bar, line, or area visualizations, you can now chart and compare previous time periods by days, weeks, months, or years. The full-screen mode toggle is located in the top right of each widget, next to the edit options. You can also select or deselect keys to customize the data displayed on the graph. Fullscreen Mode Pn # Log Search Source: https://docs.bronto.io/Search-and-Visualize/Log-Search Explore millions of log events in Bronto with the Search page, using a single search syntax with autocomplete and SQL-style filtering to analyze your data. You can refine your search results and filter out irrelevant events using Bronto's [search syntax](/query-syntax/search-syntax), which combines autocomplete with SQL-style filtering for both quick searches and more advanced queries. ## Overview To start searching logs, click on the "Logs" item in the application sidebar. Log Search overview 1. Select the logs you wish to search from the log selector on the left side of the page. One or more logs may be selected. Alternatively, turn on [Auto-resolve](#auto-resolve-datasets) and Bronto picks the datasets for you based on your query. 2. Select the time range to execute your search on. 3. Enter a search query in the search bar to filter results, or leave it empty to return all log events. Learn more about our search syntax [here](/query-syntax/search-syntax). ## Auto-resolve datasets Instead of choosing datasets yourself, you can let Bronto choose them from your query. Turn on the **Auto-resolve** switch to the right of the dataset selector, then write your query as usual. Bronto finds the datasets your query could match and searches only those. ### How datasets are chosen Auto-resolve uses every field your query names: * **Search filter**: Bronto picks the datasets your filter could match. For example, `status >= 500` only picks datasets that have a `status` field. * **Calculate and Group by**: in time series views, fields used in a calculation (such as the `duration_ms` in an average) or in **Group by** narrow the choice to datasets that also have those fields. Auto-resolve doesn't work with [full text search](/query-syntax/search-syntax#free-text-search). Bare words such as `error` match text anywhere in an event rather than a field, so Bronto can't use them to choose datasets. For full text searches, turn Auto-resolve off and select your datasets yourself. The chosen datasets update as you build your query: when you finish a condition (by typing a space, picking a suggestion, pasting, or clicking away from the search bar), when you remove a condition, and when you change **Calculate** or **Group by**. Bronto shows **Resolving…** while it works. Your current results stay on screen until you run the search. If your query doesn't name any fields, Bronto keeps the datasets it last chose. When nothing has been chosen yet, it prompts you to add a field to your query, and the **Calculate** and **Group by** field lists include fields from all of your datasets so you have somewhere to start. ### Reviewing and adjusting the chosen datasets The chosen datasets appear as chips next to the dataset selector, grouped by collection, along with a count of how many datasets will be searched. To adjust them: * Click a chip to see the datasets it contains and deselect any you don't want. * Remove a chip to drop its datasets from the search. * Use the dataset selector to add or remove datasets. Auto-resolve stays on. * Click **Clear** to empty the selection. Auto-resolve stays on and picks datasets again the next time you edit your query. Adjustments apply to the query on screen. When you edit the query, Bronto picks the datasets again and replaces your adjustments. ### Key matching Open the arrow next to the **Auto-resolve** switch to change how field names in your query are matched against the fields in your datasets. The panel shows how many datasets currently match. | **Setting** | **Options** | | - | - | | **Match** | **Exact** (default): a dataset's field name must match the name in your query. **Partial**: a dataset's field name only needs to contain it, so `status` also matches `http.status_code`. | | **Case** | **Sensitive** (default) or **Ignore**. | | **Include synonyms** | Also matches datasets that store the same information under a different field name. Bronto lists the synonyms it found; click one to replace a field in your query with it. **Partial** matching is unavailable while synonyms are on. | A dot on the arrow shows that you've changed these settings from their defaults. ### When no datasets match If no dataset matches your query, Bronto shows which field it couldn't find and doesn't run the search. Check the field's spelling, or open **Key matching** and try **Partial** matching, **Ignore** case or **Include synonyms**. If your filter matches datasets but none of them have a field used in **Calculate** or **Group by**, Bronto names that field so you can change or remove it. If the datasets couldn't be resolved, for example because of a network error, click **Retry**. ### Turning Auto-resolve off Turn the **Auto-resolve** switch off to go back to choosing datasets yourself. The datasets that were chosen stay selected, so you can carry on from them. Bronto remembers whether Auto-resolve is on for each organization in your browser. Saved searches open with the datasets they were saved with, as do links to searches where the datasets were chosen by hand; turn the switch on if you want Bronto to choose instead. Auto-resolve can't be changed while Live Tail is running. ## Search Result ### Timeline A time series showing where the results fall across the search time range is displayed immediately below the search bar. Log Search results timeline ### Event Results The log entries returned by the search are displayed in tabular format below the summary. The table has a column for each field that was configured in the fields textbox, by default all fields are shown. Clicking on any row in the table opens a sliding panel which displays various tabs related to the event which include Event Attributes, Resource Attributes and the Raw Event. From this pane you can can use keyboard arrows to view previous/next event. Log Search event details panel ### Click-to-filter from table cells Click a value in a List or Table view cell to quickly refine your results. Select **Add Filter** to add the field and value to your current query, or **Replace Filter** to replace the current query with that condition. ### View Context Use **View context** on an event to open a context view centered on the selected log entry. This lets you inspect the events immediately before and after the selected event so you can understand what happened around it without rebuilding the search manually. In the context view, Bronto keeps the selected event as the anchor and loads surrounding events in chronological order. You can also jump back to the original context event from the context view header. ### Time Series Results The time series views allow you to compute statistical functions over a specified time range, enabling deeper insights into your event data by visualizing trends and patterns. The following functions are supported: | **Function** | | **Description** | | - | - | - | | **Count** | | The total number of events within the specified time range. | | **Average** | | The average value of a specified numeric attribute in your events. | | **Min** | | The minimum value of a specified numeric attribute in your events. | | **Max** | | The maximum value of a specified numeric attribute in your events. | | **Sum** | | The total sum of a specified numeric attribute your events. | | **Median** | | The median value of a specified numeric attribute in your events. | Additionally, the time series results supports grouping data by multiple dimensions (up to 5). Group-by results are exact for up to 1000 unique groups. For example, if you group by user and action, the combination of alice, login and alice, logout counts as two distinct groups. When there are more than 1000 unique groups, an approximation is used, returning the most frequent groups. Time series results ### Automatic Parsing #### Errors & Warnings Bronto automatically detects errors and warnings in your logs enabling you to jump directly into your data for deeper analysis and faster troubleshooting. For HTTP-like logs, status codes are automatically categorized: 5xx as Error and 4xx as Warn. For application logs without a defined log level, errors are identified from stack traces, Kubernetes klog errors and Kernel Out of Memory errors. Automatic error and warning detection ## BrontoScope: AI Error Investigation When you spot an error event in your logs, BrontoScope can investigate it for you automatically. Click any error event to open the event panel, then select **Investigate with AI** to generate an AI-powered investigation report with supporting evidence. For the full workflow, capabilities, and best practices, see [BrontoScope](/ai-features/brontoscope). #### Parsing Of Attributes Bronto automatically parses the attributes in your log data for common log formats (e.g., json, syslog, apache, java gc, etc.). For uncommon unstructured or custom log formats, Bronto will parse the attributes in your log data according to the following specification for key-value pairs: A key value pair consists of a key, followed by a separator, and then a value: ``` ``` * A `` is one or more of the following characters: "` `" (space), "`,`" (comma), "`\t`" or "`\r`" or "`\n`" or "`\r\n`". * A `` is any sequence of: the alphanumeric characters, "`_`", "`.`", "`$`", and "`@`". Other characters are not allowed unless they are escaped using quotation marks, e.g., `"key[1]"` for the attribute named key\[1]. Additionally, a key must have at least one non-numeric character. * A `` is the character "=" or ":". It can be preceded and/or followed by a space. * A `` is any sequence of: the alphanumeric characters, "-", \_", ".", "\$", and "@". Quotation marks can be used to escape values with special characters, e.g., `key="hello world"` for the value "hello world". For example the following log event ``` timestamp="2025-07-15T14:32:18Z" level=INFO service="auth-service" userId=98765 ip="192.168.12.45" action=login ``` Will be parsed as * The `timestamp` attribute has the value `2025-07-15T14:32:18Z` * The `level` attribute has the value `INFO` * The `service` attribute has the value `auth-service` * The `userId` attribute has the value `98675` * The `ip` attribute has the value `192.168.12.45` * The `action` attribute has the value `login` ### Custom Parser If your log format needs more than Bronto's automatic field extraction, use **Custom Parser** to turn unstructured events into structured, queryable data tailored to your dataset. For setup, supported formats, and implementation details, see [Custom Parser](/core-features/custom-parser). ### Top Key Sampling Bronto automatically tracks the most frequently occurring keys and attributes identified during regular dataset sampling. This helps Bronto understand the most frequently occurring keys and attributes in your log data. These top keys are used to populate dropdown menus across search, dashboards, and Bronto’s monitoring features. **Note:** Less common keys may not appear in the top list. In such cases, users can manually type the desired key in auto-populated fields. ### PII Masking You can enable PII masking in Bronto to hide any personal identifiable information that may be present in your log data. To enable PII masking you must create a [custom role](https://docs.bronto.io/Account-Management/Access-Control#custom-roles) with the `Read PII Data` permission disabled, and associate the role with individual users. Users will see `********` in place of potentially sensitive information, for example: ``` user="******** ********" ip="********" msg="Hello, I'm interested in your Positive Psychology course. Please send more information to my email ********. Thanks!" ``` Currently Bronto masks the following PII by default: * Full Names * Email addresses * IPV4 & IPV6 addresses * Phone numbers Reach out to support if you require masking for other types of PII. ### Sort By Column In the "List of Events" view, you can sort events by any column in either ascending or descending order. Sort by column options Once sorted, the events will be displayed in the selected order. However, please note the following limitations: * If more than 25,000 events match your filter, only the first 25,000 matches will be included in the sort. In that case, the timeline will show a greyed-out section representing the portion of the time range that was excluded. * To sort over a larger time range, try refining your filter to match 25,000 events or fewer. For example, if you are interested in the slowest response times in some logs, you could filter using conditions like `duration_ms>2000` or `duration_ms>4000` to reduce the number of matching events. * You can view up to a maximum of 1000 events from the overall sorted set of events. Attributes are sorted alphabetically or numerically, depending on which datatype is more common for that attribute. Events that don't have the selected attribute are excluded from the sorted results. ## Timestamps & Out-of-Order Ingestion ### How Bronto Handles Timestamps Bronto attempts to parse the timestamp directly from each log event and use it for indexing. TThe timestamp must be provided in a key called timestamp or Timestamp. Common formats such as ISO 8601 are supported. If a timestamp is absent, unrecognized, or too far in the past, Bronto falls back to the **ingestion timestamp** — the time the event arrived at the platform. #### Batching Window Bronto accepts out-of-order events with timestamps up to **2 hours in the past**. Events with timestamps older than this window may not be indexed against their original event timestamp. ### Default Behavior: Parallel Ingestion By default, when multiple ingestion requests are processed in parallel, events for a dataset may arrive out of order. In this case, Bronto may reassign some timestamps during indexing to avoid adding an ingestion delay. This is acceptable for most analytical use cases — such as CDN or HTTP access logs — where aggregate patterns matter more than the precise sequence of individual events. However, in scenarios where multiple agents are batching events over longer intervals (e.g. OpenTelemetry collectors with long flush windows), this default behavior can cause spikes where many events are indexed with the same timestamp. If accurate per-event timestamps are important to you, **Out-of-Order Handling** can be enabled. ### Out-of-Order Handling When Out-of-Order Handling is enabled, Bronto will never overwrite the timestamp parsed from a log event. Instead of reassigning timestamps, Bronto sorts events before indexing them, preserving their original order. This is particularly useful for: * Logs sent in large and sparse batches by multiple agents * Any pipeline where there is a meaningful delay between event creation and delivery With Out-of-Order Handling enabled, there may be a delay before events appear in search results and dashboards, as incoming data is sorted prior to indexing. For high-volume log sources receiving events in a heavily unordered fashion, Bronto may need to delay and batch the sorting process, resulting in a maximum ingestion delay of up to **5 minutes** under normal circumstances. ### Expected Ingestion Latency Even under normal conditions, data travels via different components that may introduce lag. This includes: * Batching interval at source (e.g. an OTel batch processor) * Network transit time * Pipeline processing and parsing An end-to-end delay of up to 30 seconds is expected under normal conditions. Delays may increase during severe load spikes or incidents. No data loss will occur for packets accepted by the Bronto ingestion endpoint — acceptance is confirmed by an HTTP 200 response. ### Enabling Out-of-Order Handling Out-of-Order Handling configuration will be available directly in the Bronto UI shortly. In the meantime, contact support to have it enabled for your organisation. # Visualization Source: https://docs.bronto.io/Search-and-Visualize/Log-Visualization Visualize your data in Bronto with charts, time series, and aggregations driven by SQL queries to expose trends, errors, and performance issues. Read our [search syntax](/query-syntax/search-syntax) documentation for more information on how to write search queries. ## Overview Visualizations is a feature that allows users to displayed the data returned from searches. Using the search query editor you can select from List, Timeseries, Table, Top List, Pie Chart and Tree Map views to visualize your data. ## List List displays the results that are returned from your search query. This alows you to review a group of events. From here you can toggle to full screen mode, table view and sort results by oldest first. In List view selecting the options menu will display several toggle features which you can choose from the following options: Timeline graph, Wrap lines, date column, content column. From this option page you can also add further columns based on your results. List View Pn ## Timeseries Visualize your data over a selected timeframe. Toggle between viewing as Line graph or Bar chart. Adding further groups, the timeline will plot and graph the key and values. Timeseries View Pn ## Table A table view is a way to represent your data in a structured, tabular format. This format allows users to quickly scan and understand the data by organizing it into rows and columns depending on the fields selected. Table View Pn ## Pie Chart A pie chart can be used to visualize the distribution of various events or categories, making it easier to understand the relative frequency or importance of different types of data. Pie Pn ## Top List A top list chart is used to display the most frequent or critical events, errors, or sources, helping prioritize issues that need attention. Toplist Pn ## Tree Map Tree maps help visualize hierarchical data, showing proportions and relationships within the data set and gain valuable insights into the hierarchical structure and distribution of your data, aiding in performance monitoring, resource allocation, and issue detection. Tree Map Pn # Data Organization Source: https://docs.bronto.io/Search-and-Visualize/Partitions Organize log data in Bronto using datasets, collections, tags, and partition tags to scope queries, control access, and manage retention efficiently. ## Core Concepts: Datasets & Collections Log events in the Bronto Logging Platform are organized and stored in **datasets** and **collections**. Datasets, collections, dataset tags, and partition tags apply to **logs only**. Metrics and traces are not stored in datasets or collections: view metrics in the [Metric Explorer](/metrics/explore-metrics) and traces in [Explore Traces](/tracing/explore-traces). The `x-bronto-dataset`, `x-bronto-collection`, and `x-bronto-tags` headers therefore control log routing only. ### Datasets A **Dataset** (named `log` in the current API) is the fundamental unit of storage. It acts as a container for log events that share a similar format and origin, such as: * `application-logs` * `nginx-access` Key characteristics: * All events within the same dataset are always queried together. * The dataset **must be specified at ingestion time** by configuring the agent or integration. * The dataset and its collection are created automatically when the first log event arrives; you do not need to create them beforehand. * Dataset names must be **unique within a collection**. To learn how to configure datasets during ingestion, see the [agent setup documentation](https://docs.bronto.io/agent-setup/agent-intro). > **Note**\ > Bronto supports up to **5,000 unique datasets per organization**. *** ### Collections A **Collection** (named `logset` in the current API) is a logical grouping of datasets. Think of a collection as a folder that helps you organize related datasets and distinguish between datasets that may share the same name but come from different environments. Key points: * Collections improve discoverability and organization. * The collection can be specified using the `x-bronto-collection` HTTP header (or equivalent). * Collection configuration is described in the [agent setup documentation](https://docs.bronto.io/agent-setup/agent-intro). *** ## Tags **Tags** are key-value pairs assigned to datasets to categorize them across your system, for example: * `team:backend` * `env:production` * `type:gc` * `service:catalog` Tags make it easier to: * Select datasets in the UI * Query multiple datasets together * Build precise dashboards and monitors at scale Proper tagging is essential when managing thousands of datasets. ## Assigning Tags You can assign tags to datasets in three ways: * **Via UI**: apply or remove tags from the Logs screen * **Via API**: create tags and assign them programmatically * **At ingestion**: automatically attach tags to ingested data via the `x-bronto-tags` HTTP header (agent-level) ### Assign tags via the UI (Logs screen) Use the UI when you want to quickly apply tags to a dataset. Partitions UI 1. In the left navigation, open **Logs**. 2. Click **Select Data** dropdown. 3. Expand the relevant **Collection**. 4. Hover over the **Dataset** you want to tag. 5. Click the settings icon. 6. Select **Manage Tags**. 7. Fill out Tag Name and Value. 8. Click **Add / Apply** to confirm. ### Assign tags via the API Create a tag (and then assign/use it in your workflows) using the Tags API: * [https://docs.bronto.io/api-reference/tags/create-a-tag](https://docs.bronto.io/api-reference/tags/create-a-tag) ### Assign tags at ingestion (agent-level) Use ingestion tagging when you want tags applied automatically as data enters Bronto. Tags must be specified at the **agent level** using the `x-bronto-tags` HTTP header (or your agent’s equivalent configuration). For example: * Set `x-bronto-tags` to a comma-separated list of tags (example format may vary by agent). * The agent attaches those tags to any data it ingests. For step-by-step setup instructions (agent-specific), see: * [https://docs.bronto.io/agent-setup/agent-intro](https://docs.bronto.io/agent-setup/agent-intro) **Note:** Each dataset can have up to **10 tags**. Tags can be used simply as labels to add metadata and context, or as part of a more advanced data organization strategy using **partition tags**. *** ## Partition Tags **Partition Tags** are a special subset of tags defined at the **organization level**. They allow Bronto to automatically organize your data in a consistent and scalable way. Partition tags are especially useful for: * Large environments * Structured infrastructures * Reducing agent configuration complexity * Enforcing consistent collection and dataset placement ### How Partition Tags Work * Bronto uses partition tags to determine how incoming data is grouped into collections and datasets. * If a collection header is explicitly set, it **takes precedence** and overrides partition tag logic. * To fully leverage partition tags, omit the collection header during ingestion. ### Setup Flow: UI + Ingestion Headers 1. In **Settings -> Partition Tags**, enable partition tags and define the hierarchy order (broadest to most specific). 2. Update your ingestion agent config so `x-bronto-tags` includes the same tag keys you configured as partition tags. ```bash theme={"dark"} x-bronto-tags: environment=production,region=us-east-1,service=api-gateway ``` Defining partition tags in the UI is not enough by itself. Bronto can only apply the partition hierarchy when those keys are present at ingestion time via the `x-bronto-tags` header. If partition tag keys are missing in incoming logs, data will not be grouped into the expected partition hierarchy and can appear under unexpected dataset groupings. 3. Open **Logs** and verify the partition tags appear in the dataset selector. *** ## Choosing Your Partition Tags Partition tags define your data hierarchy, so they should be chosen carefully—ideally during the initial account configuration. ### Characteristics of Good Partition Tags Partition tags should: * Be **low-cardinality** * Represent attributes that are **intrinsically tied to the data source** * Remain **stable over time** **Good examples:** * `environment` * `region` * `datacenter` * `account` * `cluster` * `service` * `product` **Bad examples:** * `team`\ Teams and responsibilities change frequently. Team ownership is valuable metadata, but not suitable for defining data hierarchy. * High-cardinality or volatile attributes such as: * `hostname` * `instance_id` * `pod_id` * `ip_address` These attributes change often and can lead to excessive dataset creation. They also do not make sense as dataset tags and should instead be included at the **log event level**. > **Warning**\ > While partition tags can be modified at any time, changing them on live data is a **sensitive operation**. Updates may cause new datasets to be created for existing streams, potentially breaking dashboards, monitors, and saved queries. *** ## Example: Designing Partition Tags ### Context Your infrastructure includes: * **Environments**: `staging`, `production` * **Regions**: `eu`, `us` * **Services**: `catalog`, `checkout`, `payment`, `cart` * **Teams**: `team-a`, `team-b` Each service produces multiple log streams, such as: * Syslog * Application logs * Garbage collection logs ### Recommended Partition Tags * environment * region * service Why this works: * These descriptors are stable and directly tied to where and what generates logs. * They clearly identify the source of the data. * They scale well as your infrastructure grows. In this setup: * The **dataset name** should represent the log stream (e.g., `application`, `gc`, `syslog`). * Collections and datasets are automatically and consistently organized. ### Why Not Use `team` as a Partition Tag? Team ownership changes over time. If a service moves from `team-a` to `team-b`: * The partition tag combination changes * New datasets are created for the same service * Old datasets stop receiving data * Existing dashboards, monitors, and queries may break or return incomplete results **Best practice:**\ Use `team` as a **regular tag**, not a partition tag. This allows you to update ownership metadata without disrupting your data organization or historical visibility. # Saved Searches Source: https://docs.bronto.io/Search-and-Visualize/Saved-Searches Save search queries, filters, and column layouts as Saved Searches in Bronto so your team can quickly switch between troubleshooting contexts. ## Overview The Saved Searches panel groups your searches into **Favourites**, **Created by Me** and **Created by Others**, so you can separate your own work from searches shared across your account. A **By Tag** group also appears once any of your saved searches are tagged. The Saved Searches panel in Bronto Log Search A saved search stores the selected data, the search query, any visualisation you had selected, and your column selection and ordering. **From the Saved Searches panel you can:** * Load or reload a saved search. * Edit, add to favourites, or delete a saved search from its `...` menu. **How to create a Saved Search:** * Run a search using the conditions you want to save or share. * Click **Save Current Search** at the top of the panel. A new panel will appear where you can enter a name for your saved search. * Enter a name and click Save to confirm. Column selection and ordering have been stored with saved searches since July 2025. Searches created before then have no stored column layout, so Bronto derives a sensible default from the log type when you load them. # Agent Setup Source: https://docs.bronto.io/agent-setup/agent-intro Configure a telemetry agent to collect and forward log data to Bronto. Supports OpenTelemetry, Fluent Bit, Fluentd, Logstash, Datadog Agent, and Vector. Bronto supports multiple telemetry agents for log collection and forwarding. Choose the agent that fits your existing infrastructure — each guide covers configuration and verification, and links out to the agent's own installation documentation. ### Generate an API Key Before configuring your chosen agent, create an [API Key](/Account-Management/API-Keys). Store it securely — Bronto does not display the full key again after generation. You must have admin privileges to create API keys. ## Supported Agents | Agent | Description | | - | - | | [OpenTelemetry](/agent-setup/open-telemetry) | Vendor-neutral observability framework for collecting logs, metrics, and traces | | [Odigos](/agent-setup/odigos) | Kubernetes-native platform that auto-instruments workloads with eBPF and forwards their traces, metrics, and logs | | [Fluent Bit](/agent-setup/fluent-bit) | Lightweight, high-performance log processor and forwarder | | [Fluentd](/agent-setup/fluentd) | Open-source data collector for unified logging | | [Logstash](/agent-setup/logstash) | Data processing pipeline from the Elastic stack | | [Datadog Agent](/agent-setup/datadog-agent) | Forward logs via the Datadog Agent to Bronto | | [Vector](/agent-setup/vector) | High-performance observability data pipeline | ## Choose Agent
OpenTelemetry
Odigos
Fluent Bit
Fluentd
Logstash
Datadog
Vector
# Configure Datadog Agent Source: https://docs.bronto.io/agent-setup/datadog-agent Forward logs to Bronto using the Datadog Agent, ideal for migrating existing Datadog-based pipelines without changing your application instrumentation. The Datadog Agent can forward logs to Bronto in addition to Datadog using the `additional_endpoints` configuration. This page covers configuration only. For installation instructions, see the [Datadog Agent documentation](https://docs.datadoghq.com/agent/). ## Endpoint and authentication Use the ingestion endpoint for your Bronto region: | Region | Host | | - | - | | EU | `ingestion.eu.bronto.io` | | US | `ingestion.us.bronto.io` | Set `api_key` to your [Bronto API key](/Account-Management/API-Keys#create-a-new-api-key). ## Configuration Edit `~/.datadog-agent/datadog.yaml` to add Bronto as an additional log endpoint: ```yaml datadog.yaml theme={"dark"} logs_config: additional_endpoints: - api_key: "" host: "ingestion..bronto.io" port: 443 is_reliable: true ``` By default, the dataset and collection where logs are sent are derived from the `service` and `source` tags reported by the Datadog Agent. These can be overridden with the `br_dataset` and `br_collection` log attributes if required. Add Bronto as an additional endpoint by upgrading the Datadog Agent Helm chart: ```bash theme={"dark"} helm upgrade datadog-agent -f datadog-values.yaml datadog/datadog ``` ```yaml datadog-values.yaml theme={"dark"} datadog: podAnnotationsAsTags: kubernetes.annotations.logs.bronto.io/collection: br_collection logs: enabled: true customAgentConfig: logs_config: additional_endpoints: - api_key: "" host: "ingestion..bronto.io" port: 443 is_reliable: true ``` Add the `kubernetes.annotations.logs.bronto.io/collection` annotation to pods whose logs should be forwarded to Bronto. Set its value to a unique identifier for the cluster, e.g. `--`. The `podAnnotationsAsTags` entry maps this annotation to the `br_collection` log attribute, which Bronto uses to determine which collection to save the log data under. For the full `additional_endpoints` configuration reference, see the [Datadog Agent log forwarding documentation](https://docs.datadoghq.com/agent/logs/?tab=tailfiles#send-logs-to-a-custom-endpoint). ## Verify Log Collection Once you have applied your configuration and restarted the Datadog Agent, you can expect to see your log data being ingested to Bronto and accessible via the [Search](https://app.bronto.io/search) page. # Connect Fluent Bit to Bronto Source: https://docs.bronto.io/agent-setup/fluent-bit Configure the Fluent Bit log processor to collect application and system logs, batch them, and forward to Bronto over HTTP for search and analysis. Fluent Bit forwards logs to Bronto using its built-in HTTP output plugin. This page covers Fluent Bit configuration only. For installation instructions, see the [Fluent Bit installation guide](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit). For the full Fluent Bit configuration reference, see the [Fluent Bit documentation](https://docs.fluentbit.io/manual/administration/configuring-fluent-bit). ## Endpoint and authentication Use the ingestion endpoint for your Bronto region: | Region | Host | | - | - | | EU | `ingestion.eu.bronto.io` | | US | `ingestion.us.bronto.io` | Every request requires these headers: | Header | Required | Description | | - | - | - | | `x-bronto-api-key` | Required | Your [Bronto API key](/Account-Management/API-Keys#create-a-new-api-key). | | `x-bronto-dataset` | Required | The dataset to route logs to. | | `x-bronto-collection` | Required | The collection to group datasets under. | | `x-bronto-tags` | Optional | Key-value tag pairs (e.g. `env=prod,team=platform`). See [Partitions](/Search-and-Visualize/Partitions). | ## Minimal configuration Tail a single log file and forward to Bronto. ```ini fluent-bit.conf theme={"dark"} [SERVICE] flush 1 daemon off log_level info [INPUT] name tail path /path/to/your/logs tag app.logs refresh_interval 5 mem_buf_limit 5MB skip_long_lines on [OUTPUT] name http tls on match * host ingestion..bronto.io port 443 format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset header x-bronto-collection ``` For the full HTTP output configuration reference, see the [Fluent Bit HTTP output documentation](https://docs.fluentbit.io/manual/pipeline/outputs/http). ## Parsing unstructured logs Rather than building Fluent Bit parsers for unstructured text, ship raw log lines to Bronto and use the [Bronto Custom Parser](/core-features/custom-parser) to extract structured fields server-side. The Custom Parser uses LLMs to generate parsers automatically and ships with built-in support for Apache, IIS, HAProxy, Syslog, key-value, and custom formats — no regex maintenance required. ## Common patterns The patterns below cover configuration concerns most Bronto customers run into. ### Adding metadata to every log Use the `record_modifier` filter to inject metadata — e.g. a deployment identifier, branch name, or region — from environment variables. Export the variable from your CI/CD pipeline or container runtime, then reference it in your Fluent Bit config. ```bash theme={"dark"} export APP_GIT_BRANCH="feature-branch-name" ``` ```ini fluent-bit.conf theme={"dark"} [FILTER] name record_modifier match * record branch ${APP_GIT_BRANCH} ``` ### Multi-line logs (stack traces) Multi-line application output — like Java, Python, or Ruby stack traces — must be reassembled at the input stage so each stack trace ships as a single log record. Use the `multiline.parser` directive on `[INPUT]`. Fluent Bit ships with parsers for `java`, `python`, `ruby`, `go`, `dotnet`, and others. ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/app.log tag app.logs multiline.parser python ``` `multiline.parser` at the `[INPUT]` level requires Fluent Bit 1.8 or later. ### Routing multiple log sources to separate datasets A single Fluent Bit instance can ship logs from multiple applications to different Bronto datasets. Tag each `[INPUT]` distinctly, then use `Match` on each `[OUTPUT]`. ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/api.log tag api.logs [INPUT] name tail path /var/log/worker.log tag worker.logs [OUTPUT] name http tls on match api.logs host ingestion..bronto.io port 443 format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset api-service header x-bronto-collection [OUTPUT] name http tls on match worker.logs host ingestion..bronto.io port 443 format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset worker-service header x-bronto-collection ``` The `Match` field is the routing mechanism — a filter or output with `Match api.logs` will never apply to `worker.logs`, and vice versa. A filter with `Match *` applies to every stream. ### Kubernetes For Kubernetes deployments, install Fluent Bit as a DaemonSet via the [official Helm chart](https://github.com/fluent/helm-charts) and use the `x-bronto-collection` header to identify the cluster. Dataset names are inferred from Kubernetes metadata. ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/containers/*.log multiline.parser docker, cri tag kube.* mem_buf_limit 5MB skip_long_lines on [FILTER] name kubernetes match kube.* k8s-logging.parser on k8s-logging.exclude on [OUTPUT] name http tls on match kube.* host ingestion..bronto.io port 443 format json_lines compress gzip header x-bronto-api-key header x-bronto-collection -- ``` ## Verify log collection Once you have applied your configuration and restarted Fluent Bit, you can expect to see your log data being ingested to Bronto and accessible via the [Search](https://app.bronto.io/search) page. ## Further reading * [Fluent Bit installation](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) * [Fluent Bit configuration reference](https://docs.fluentbit.io/manual/administration/configuring-fluent-bit) * [Multiline parsing](https://docs.fluentbit.io/manual/administration/configuring-fluent-bit/multiline-parsing) * [Fluent Bit Helm chart](https://github.com/fluent/helm-charts) — for Kubernetes * [Bronto Custom Parser](/core-features/custom-parser) — extract structured fields from unstructured logs # Connect Fluentd to Bronto Source: https://docs.bronto.io/agent-setup/fluentd Configure the Fluentd open-source data collector to tail application log files and forward structured events to Bronto over HTTP with batching and retries. Fluentd forwards logs to Bronto using its built-in `http` output plugin. This page covers Fluentd configuration only. For installation instructions, see the [Fluentd installation guide](https://docs.fluentd.org/installation). For the full Fluentd configuration reference, see the [Fluentd documentation](https://docs.fluentd.org/configuration). ## Endpoint and authentication Use the ingestion endpoint for your Bronto region: | Region | Endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io:443` | | US | `https://ingestion.us.bronto.io:443` | Every request requires these headers: | Header | Required | Description | | - | - | - | | `x-bronto-api-key` | Required | Your [Bronto API key](/Account-Management/API-Keys#create-a-new-api-key). | | `x-bronto-dataset` | Required | The dataset to route logs to. | | `x-bronto-collection` | Required | The collection to group datasets under. | | `x-bronto-tags` | Optional | Key-value tag pairs (e.g. `env=prod,team=platform`). See [Partitions](/Search-and-Visualize/Partitions). | ## Minimal configuration Tail a JSON log file and forward to Bronto. ```xml /etc/fluent/fluentd.conf theme={"dark"} @type tail path /path/to/your/logs tag app.logs refresh_interval 5s @type json pos_file /var/log/td-agent/buffer/fluentd.pos @type http endpoint https://ingestion..bronto.io:443 http_method post @type file path /var/log/td-agent/buffer/http flush_interval 10s chunk_limit_size 5MB overflow_action block @type json headers {"x-bronto-api-key": "", "x-bronto-dataset": "", "x-bronto-collection": ""} ``` For the full HTTP output configuration reference, see the [Fluentd HTTP output documentation](https://docs.fluentd.org/output/http). ## Parsing unstructured logs Rather than building Fluentd parsers for unstructured text, ship raw log lines to Bronto and use the [Bronto Custom Parser](/core-features/custom-parser) to extract structured fields server-side. The Custom Parser uses LLMs to generate parsers automatically and ships with built-in support for Apache, IIS, HAProxy, Syslog, key-value, and custom formats — no regex maintenance required. ## Common patterns ### Adding metadata to every log Use the `record_transformer` filter to inject metadata into every record. Values can be expressions (Ruby) or environment variables. ```xml theme={"dark"} @type record_transformer hostname "#{Socket.gethostname}" branch "#{ENV['APP_GIT_BRANCH']}" ``` ### Routing multiple log sources to separate datasets Tag each `` distinctly, then use a separate `` block for each tag with the appropriate `x-bronto-dataset` header. ```xml theme={"dark"} @type tail path /var/log/api.log tag api.logs @type json pos_file /var/log/td-agent/buffer/api.pos @type tail path /var/log/worker.log tag worker.logs @type json pos_file /var/log/td-agent/buffer/worker.pos @type http endpoint https://ingestion..bronto.io:443 http_method post @type json headers {"x-bronto-api-key": "", "x-bronto-dataset": "api-service", "x-bronto-collection": ""} @type http endpoint https://ingestion..bronto.io:443 http_method post @type json headers {"x-bronto-api-key": "", "x-bronto-dataset": "worker-service", "x-bronto-collection": ""} ``` ## Verify log collection Once you have applied your configuration and restarted Fluentd, you can expect to see your log data being ingested to Bronto and accessible via the [Search](https://app.bronto.io/search) page. ## Further reading * [Fluentd installation](https://docs.fluentd.org/installation) * [Fluentd configuration reference](https://docs.fluentd.org/configuration) * [`http` output plugin](https://docs.fluentd.org/output/http) * [Buffering](https://docs.fluentd.org/configuration/buffer-section) * [Bronto Custom Parser](/core-features/custom-parser) — extract structured fields from unstructured logs # Connect Logstash to Bronto Source: https://docs.bronto.io/agent-setup/logstash Configure the Logstash data processing pipeline with an HTTP output to enrich, transform, and forward log events from your applications to Bronto. Logstash forwards logs to Bronto using its built-in `http` output plugin. This page covers Logstash configuration only. For installation instructions, see the [Logstash installation guide](https://www.elastic.co/guide/en/logstash/current/installing-logstash.html). For the full Logstash configuration reference, see the [Logstash documentation](https://www.elastic.co/guide/en/logstash/current/configuration.html). ## Endpoint and authentication Use the ingestion endpoint for your Bronto region: | Region | Endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | Every request requires these headers: | Header | Required | Description | | - | - | - | | `x-bronto-api-key` | Required | Your [Bronto API key](/Account-Management/API-Keys#create-a-new-api-key). | | `x-bronto-dataset` | Required | The dataset to route logs to. | | `x-bronto-collection` | Required | The collection to group datasets under. | | `x-bronto-tags` | Optional | Key-value tag pairs (e.g. `env=prod,team=platform`). See [Partitions](/Search-and-Visualize/Partitions). | ## Minimal configuration Tail a log file and forward to Bronto. ```ruby /etc/logstash/conf.d/bronto.conf theme={"dark"} input { file { id => "app_input" path => "/path/to/your/logs" } } output { http { id => "bronto_output" url => "https://ingestion..bronto.io" http_method => "post" format => "json" headers => { "x-bronto-api-key" => "" "x-bronto-dataset" => "" "x-bronto-collection" => "" } } } ``` For the full HTTP output configuration reference, see the [Logstash HTTP output documentation](https://www.elastic.co/guide/en/logstash/current/plugins-outputs-http.html). ## Parsing unstructured logs Rather than building grok patterns inside Logstash, ship raw log lines to Bronto and use the [Bronto Custom Parser](/core-features/custom-parser) to extract structured fields server-side. The Custom Parser uses LLMs to generate parsers automatically and ships with built-in support for Apache, IIS, HAProxy, Syslog, key-value, and custom formats — no regex maintenance required. ## Common patterns The patterns below cover configuration concerns most Bronto customers run into. ### Adding metadata to every log Use the `mutate` filter to inject metadata — e.g. a deployment identifier, branch name, or region — into every event. Values can be referenced from environment variables via `${VAR}`. ```ruby theme={"dark"} filter { mutate { add_field => { "branch" => "${APP_GIT_BRANCH}" "environment" => "${APP_ENV}" } } } ``` ### Multi-line logs (stack traces) Multi-line application output — like Java, Python, or Ruby stack traces — must be reassembled at the input stage so each stack trace ships as a single log record. Use the `multiline` codec on the input. ```ruby theme={"dark"} input { file { id => "app_input" path => "/var/log/app.log" codec => multiline { pattern => "^\s" what => "previous" } } } ``` The pattern above appends any line beginning with whitespace to the previous line — a common heuristic for stack traces. Adjust the pattern for your log format. See the [multiline codec documentation](https://www.elastic.co/guide/en/logstash/current/plugins-codecs-multiline.html) for details. ### Routing multiple log sources to separate datasets A single Logstash instance can ship logs from multiple applications to different Bronto datasets. Tag each input distinctly, then use a conditional on each output. ```ruby /etc/logstash/conf.d/bronto.conf theme={"dark"} input { file { id => "api_input" path => "/var/log/api.log" tags => ["api"] } file { id => "worker_input" path => "/var/log/worker.log" tags => ["worker"] } } output { if "api" in [tags] { http { id => "bronto_api" url => "https://ingestion..bronto.io" http_method => "post" format => "json" headers => { "x-bronto-api-key" => "" "x-bronto-dataset" => "api-service" "x-bronto-collection" => "" } } } if "worker" in [tags] { http { id => "bronto_worker" url => "https://ingestion..bronto.io" http_method => "post" format => "json" headers => { "x-bronto-api-key" => "" "x-bronto-dataset" => "worker-service" "x-bronto-collection" => "" } } } } ``` ## Verify log collection Once you have applied your configuration and restarted Logstash, you can expect to see your log data being ingested to Bronto and accessible via the [Search](https://app.bronto.io/search) page. ## Further reading * [Logstash installation](https://www.elastic.co/guide/en/logstash/current/installing-logstash.html) * [Logstash configuration reference](https://www.elastic.co/guide/en/logstash/current/configuration.html) * [`http` output plugin](https://www.elastic.co/guide/en/logstash/current/plugins-outputs-http.html) * [`multiline` codec](https://www.elastic.co/guide/en/logstash/current/plugins-codecs-multiline.html) * [Bronto Custom Parser](/core-features/custom-parser) — extract structured fields from unstructured logs # Connect Odigos to Bronto Source: https://docs.bronto.io/agent-setup/odigos Configure Odigos to auto-instrument Kubernetes workloads with eBPF and forward their traces, metrics, and logs to Bronto over OTLP. Odigos auto-instruments Kubernetes workloads with eBPF and forwards their traces, metrics, and logs to Bronto via OTLP/HTTP. Unlike the other agents on this page, it also **generates** the telemetry: your applications need no SDK, no code changes, and no rebuilt images. This page covers Odigos destination configuration only. For installation instructions, see the [Odigos installation guide](https://docs.odigos.io/setup/installation). ## Endpoint and authentication Use the endpoints for your Bronto region: | Region | Logs endpoint | Metrics endpoint | Traces endpoint | | - | - | - | - | | EU | `https://ingestion.eu.bronto.io/v1/logs` | `https://ingestion.eu.bronto.io/v1/metrics` | `https://ingestion.eu.bronto.io/v1/traces` | | US | `https://ingestion.us.bronto.io/v1/logs` | `https://ingestion.us.bronto.io/v1/metrics` | `https://ingestion.us.bronto.io/v1/traces` | Bronto authenticates with a header rather than basic auth or a bearer token, so the API key goes in the destination's `OTLP_HTTP_HEADERS` field: | Header | Required | Scope | Description | | - | - | - | - | | `x-bronto-api-key` | Required | All signals | Your [Bronto API key](/Account-Management/API-Keys#create-a-new-api-key). | | `x-bronto-dataset` | Optional | Logs only | Overrides `service.name` as the log dataset. | | `x-bronto-collection` | Optional | Logs only | Overrides `service.namespace` as the log collection. | ## Minimal configuration Create a `Destination` resource in the `odigos-system` namespace. `OTLP_HTTP_HEADERS` takes a JSON array of `{"key": ..., "value": ...}` objects. ```yaml bronto-destination.yaml theme={"dark"} apiVersion: odigos.io/v1alpha1 kind: Destination metadata: name: bronto namespace: odigos-system spec: type: otlphttp destinationName: bronto signals: - TRACES - METRICS - LOGS data: OTLP_HTTP_ENDPOINT: "https://ingestion..bronto.io" OTLP_HTTP_TRACES_ENDPOINT: "https://ingestion..bronto.io/v1/traces" OTLP_HTTP_METRICS_ENDPOINT: "https://ingestion..bronto.io/v1/metrics" OTLP_HTTP_LOGS_ENDPOINT: "https://ingestion..bronto.io/v1/logs" OTLP_HTTP_COMPRESSION: "gzip" OTLP_HTTP_TLS_ENABLED: "true" OTLP_HTTP_HEADERS: '[{"key":"x-bronto-api-key","value":""}]' ``` ```bash theme={"dark"} kubectl apply -f bronto-destination.yaml ``` The same destination can be added through the Odigos UI (`odigos ui`) by selecting **OTLP http** and entering the endpoints and header. Odigos does not treat custom headers as secret, so the API key is stored in plain text in the `Destination` resource rather than in a Kubernetes `Secret`. Restrict RBAC on the `odigos-system` namespace, and avoid committing the manifest to source control. ## Send only the signals you need `spec.signals` controls which pipelines Odigos builds. Remove any of `TRACES`, `METRICS`, or `LOGS` to stop sending that signal; the corresponding endpoint field can be removed with it. Bronto supports sums, gauges, summaries, and explicit histograms. Sum and histogram metrics can be ingested as delta or cumulative, but delta is strongly recommended to get the best value from the current set of supported functions. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). ## Instrumenting workloads Odigos only instruments workloads you mark as sources: ```bash theme={"dark"} odigos sources create -src \ --workload-kind=Deployment \ --workload-name= \ --workload-namespace= \ -n ``` Odigos rolls the affected pods once to attach instrumentation. Confirm agents are attached with `kubectl -n get instrumentationinstances`. Odigos derives `service.name` from the workload name and attaches it to every signal. For logs, this becomes the Bronto dataset name. Traces and metrics are not stored in datasets or collections; use `service.name` and the Kubernetes attributes as filters in [Explore Traces](/tracing/explore-traces) and the [Metric Explorer](/metrics/explore-metrics). Every span is enriched with `k8s.deployment.name`, `k8s.namespace.name`, `k8s.pod.name`, `k8s.node.name`, and `k8s.container.name`, so you can scope traces to a workload, namespace, or node. ## Verify delivery Once the destination is applied and your sources are instrumented: * Traces appear in [Explore Traces](/tracing/explore-traces). * Metrics appear in the Metric Explorer. * Logs appear in [Search](https://app.bronto.io/search). To confirm the exporter was generated, inspect the gateway collector's configuration: ```bash theme={"dark"} kubectl -n odigos-system get cm odigos-gateway \ -o jsonpath='{.data.collector-conf}' | grep -A6 bronto ``` Export failures are logged by the gateway. A `401` means the API key or the region is wrong — a region mismatch returns the same status as an invalid key. ```bash theme={"dark"} kubectl -n odigos-system logs -l odigos.io/collector-role=CLUSTER_GATEWAY --tail=200 | grep -i "error\|failed" ``` ## Further reading * [Odigos documentation](https://docs.odigos.io) — sources, actions, and destination reference * [Zero-code instrumentation with eBPF](/opentelemetry/ebpf) — instrument without adopting a platform * [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) — if you already run your own Collector * [Send Traces to Bronto](/tracing/send-traces) — including direct SDK export * [Send Metrics to Bronto](/metrics/send-metrics) — supported metric types and limitations # Connect OpenTelemetry Collector to Bronto Source: https://docs.bronto.io/agent-setup/open-telemetry Deploy the OpenTelemetry Collector with OTLP exporters to receive, process, and forward logs, metrics, and traces to Bronto, including on Kubernetes. The OpenTelemetry Collector forwards logs, metrics, and traces to Bronto via OTLP/HTTP. This page covers Collector configuration only. For installation instructions, see the [OpenTelemetry Collector documentation](https://opentelemetry.io/docs/collector/installation/). For SDK-based instrumentation, see Bronto's [language-specific OpenTelemetry guides](/opentelemetry/overview). ## Getting your data into the Collector The Collector only forwards the telemetry it **receives** — deploying it does not automatically discover your logs. If you've configured the Collector but aren't seeing all the logs you expect, the source usually hasn't been wired up to send data to it yet. There are two categories of source: * **Application logs, metrics, and traces** — instrument your application with the OpenTelemetry SDK so it exports OTLP to the Collector (or directly to Bronto). See [Ingest OpenTelemetry data](/opentelemetry/overview) for per-language setup. Alternatively, point the `filelog` receiver at the log files your application already writes. * **Infrastructure and service logs** — each source has its own setup. See [Ingesting Infrastructure and Database Logs](/integrations/infrastructure-overview) for the full list (Kubernetes, Docker, NGINX, databases, message brokers, and more), and [Collecting Windows OS Logs and Metrics](/integrations/azure-windows-logs) for Windows Event Log, IIS, and Windows performance-counter metrics. The receiver examples on this page show the Collector-side plumbing; the source guides above show what each source emits and where it writes its logs. ## Endpoints Use the endpoints for your Bronto region: | Region | Logs endpoint | Metrics endpoint | Traces endpoint | | - | - | - | - | | EU | `https://ingestion.eu.bronto.io/v1/logs` | `https://ingestion.eu.bronto.io/v1/metrics` | `https://ingestion.eu.bronto.io/v1/traces` | | US | `https://ingestion.us.bronto.io/v1/logs` | `https://ingestion.us.bronto.io/v1/metrics` | `https://ingestion.us.bronto.io/v1/traces` | The OTel Collector uses `service.name` and `service.namespace` as shared resource identity across all three signals. For logs, Bronto also uses them to select the dataset and collection. Only the API key header is required; the rest are optional log-routing overrides: Datasets and collections apply only to logs. Metrics appear in the [Metric Explorer](/metrics/explore-metrics), and traces appear in [Explore Traces](/tracing/explore-traces). Neither signal creates a dataset or collection, and the log-routing headers below do not organize them. | Header | Required | Scope | Description | | - | - | - | - | | `x-bronto-api-key` | Required | All signals | Your [Bronto API key](/Account-Management/API-Keys#create-a-new-api-key). | | `x-bronto-dataset` | Optional | Logs only | Overrides `service.name` as the log dataset. | | `x-bronto-collection` | Optional | Logs only | Overrides `service.namespace` as the log collection. | | `x-bronto-tags` | Optional | Logs only | Key-value dataset tags (e.g. `env=prod,team=platform`). See [Partitions](/Search-and-Visualize/Partitions). | ## Logs, metrics, and traces Run all three pipelines through a single Collector. Tail log files via the `filelog` receiver, accept OTLP metrics and traces from your applications via the `otlp` receiver, and ship each signal to its Bronto endpoint. The example uses the standard OTLP receiver ports: `4317` for gRPC and `4318` for HTTP. Applications on the same host commonly use `localhost`; containers, Kubernetes workloads, remote Collectors, and TLS-enabled deployments require an address and scheme appropriate to that environment. Keep the SDK exporter and Collector receiver settings aligned. ```yaml /etc/otel/config.yaml theme={"dark"} receivers: filelog/app: include: - /path/to/your/logs resource: service.name: service.namespace: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: cumulativetodelta: initial_value: drop exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: otlphttp/brontometrics: metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" compression: gzip headers: x-bronto-api-key: otlphttp/brontotraces: traces_endpoint: "https://ingestion..bronto.io/v1/traces" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/app] processors: [batch] exporters: [otlphttp/brontologs] metrics: receivers: [otlp] processors: [cumulativetodelta, batch] exporters: [otlphttp/brontometrics] traces: receivers: [otlp] processors: [batch] exporters: [otlphttp/brontotraces] ``` The `service.name` and `service.namespace` resource attributes are shared across all three signals. Bronto uses them to route **logs** to the correct dataset and collection; the log exporter can override them with the `x-bronto-dataset` and `x-bronto-collection` headers. For metrics and traces, the attributes remain source identity and filters, without creating datasets or collections. Bronto supports sums, gauges, summaries, and explicit histograms. Sum and histogram metrics can be ingested as delta or cumulative, but delta is strongly recommended to get the best value from the current set of supported functions. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). For signal-specific details, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). ## Send only the signals you need Collector pipelines are independent. To send only one signal or a subset, remove the unused signal pipelines and exporters. You do not need a separate Collector. ## Windows hosts On Windows, the `filelog` receiver picks up file-based logs (IIS, SQL Server, application files), but most platform and service diagnostics are written to the **Windows Event Log** and need the Windows-only `windowseventlog` receiver instead. See [Collecting Windows OS Logs and Metrics](/integrations/azure-windows-logs) for the receiver configuration, the event channels worth collecting, XPath filtering for noisy channels, Windows `filelog` gotchas (UTF-16 encoding, multi-line stack traces), and running the Collector as a Windows service. ## Parsing unstructured logs Rather than building parser operators in the Collector for unstructured text, ship raw log lines to Bronto and use the [Bronto Custom Parser](/core-features/custom-parser) to extract structured fields server-side. The Custom Parser uses LLMs to generate parsers automatically and ships with built-in support for Apache, IIS, HAProxy, Syslog, key-value, and custom formats — no regex maintenance required. ## Kubernetes For Kubernetes deployments, install the Collector using the [OpenTelemetry Helm chart](https://github.com/open-telemetry/opentelemetry-helm-charts/tree/main/charts/opentelemetry-collector). ```bash theme={"dark"} helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts helm install otel-collector open-telemetry/opentelemetry-collector \ --values values.yaml ``` Use the `x-bronto-collection` header on the **logs exporter** to identify the cluster (e.g. `cluster1-prod-us-east-1`). Bronto infers log dataset names from log resource attributes, so per-service log routing is handled automatically. Metrics and traces retain Kubernetes and service resource attributes for filtering in their respective explorers. ```yaml values.yaml theme={"dark"} mode: daemonset config: receivers: filelog: include: - /var/log/pods/*/*/*.log otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: cumulativetodelta: initial_value: drop k8sattributes: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: x-bronto-collection: -- otlphttp/brontometrics: metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" compression: gzip headers: x-bronto-api-key: otlphttp/brontotraces: traces_endpoint: "https://ingestion..bronto.io/v1/traces" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog] processors: [k8sattributes, batch] exporters: [otlphttp/brontologs] metrics: receivers: [otlp] processors: [k8sattributes, cumulativetodelta, batch] exporters: [otlphttp/brontometrics] traces: receivers: [otlp] processors: [k8sattributes, batch] exporters: [otlphttp/brontotraces] ``` The `k8sattributes` processor enriches logs, metrics, and traces with pod, namespace, and node metadata. See the [OpenTelemetry Demo Kubernetes deployment guide](https://opentelemetry.io/docs/demo/kubernetes-deployment/#bring-your-own-backend) for further context on backend configuration. ## Verify delivery Once your configuration is applied and the Collector is restarted: * Logs appear in [Search](https://app.bronto.io/search). * Metrics appear in the Metric Explorer. * Traces appear in [Explore Traces](/tracing/explore-traces). ## Further reading * [OpenTelemetry Collector configuration](https://opentelemetry.io/docs/collector/configuration/) — full receiver/processor/exporter reference * [OpenTelemetry Helm chart](https://github.com/open-telemetry/opentelemetry-helm-charts/tree/main/charts/opentelemetry-collector) — for Kubernetes * [Send Traces to Bronto](/tracing/send-traces) — including direct SDK export * [Send Metrics to Bronto](/metrics/send-metrics) — supported metric types and limitations * [Bronto OpenTelemetry SDK guides](/opentelemetry/overview) — language-specific instrumentation * [Bronto Custom Parser](/core-features/custom-parser) — extract structured fields from unstructured logs # Connect Vector to Bronto Source: https://docs.bronto.io/agent-setup/vector Configure the Vector observability data pipeline to collect, transform, and forward host, container, and application logs to Bronto over HTTP. Vector forwards logs to Bronto using its built-in HTTP sink. This page covers Vector configuration only. For installation instructions, see the [Vector installation guide](https://vector.dev/docs/setup/installation/). ## Endpoint and authentication Use the ingestion endpoint for your Bronto region: | Region | Host | | - | - | | EU | `https://ingestion.eu.bronto.io:443` | | US | `https://ingestion.us.bronto.io:443` | Every request requires these headers: | Header | Required | Description | | - | - | - | | `x-bronto-api-key` | Required | Your [Bronto API key](/Account-Management/API-Keys#create-a-new-api-key). | | `x-bronto-dataset` | Required | The dataset to route logs to. | | `x-bronto-collection` | Required | The collection to group datasets under. | | `x-bronto-tags` | Optional | Key-value tag pairs (e.g. `env=prod,team=platform`). See [Partitions](/Search-and-Visualize/Partitions). | ## Minimal configuration Tail a log file and forward to Bronto. ```yaml /etc/vector/vector.yaml theme={"dark"} sources: app_logs: type: file include: - /path/to/your/logs sinks: bronto: type: "http" inputs: ["app_logs"] uri: "https://ingestion..bronto.io:443/" compression: "gzip" encoding: codec: "json" framing: method: "newline_delimited" method: "post" request: headers: x-bronto-api-key: x-bronto-dataset: x-bronto-collection: ``` For the full HTTP sink configuration reference, see the [Vector HTTP sink documentation](https://vector.dev/docs/reference/configuration/sinks/http/). ## Verify Log Collection Once you have applied your configuration and restarted Vector, you can expect to see your log data being ingested to Bronto and accessible via the [Search](https://app.bronto.io/search) page. # AI Investigation Reports Source: https://docs.bronto.io/ai-features/ai-investigation-reports Run automated AI investigations when a Bronto monitor fires, with prompt-guided analysis and reports covering likely causes, impact, and next steps. AI Investigation Reports let Bronto run an automated investigation when a monitor fires. Instead of starting from a blank page after an alert, responders receive an AI-generated report shaped by the context you provide in the monitor configuration. *** ## Overview When enabled on a monitor, Bronto sends the alert context and your **Investigation Prompt** into an AI-driven investigation workflow. The report is delivered as a follow-up to the monitor notification and is designed to help responders move from alert to diagnosis faster. This feature is best suited to recurring operational issues where the monitor already points to a meaningful failure signal, but responders still need help checking dependencies, related datasets, or likely impact. AI Investigation Report monitor configuration *** ## How It Works 1. Create or edit a monitor in Bronto 2. Enable **AI Investigation Report** 3. Enter an **Investigation Prompt** 4. Save the monitor and configure notifications as usual 5. When the monitor fires, Bronto runs an investigation automatically 6. Review the report that follows the alert notification *** ## What To Configure ### AI Investigation Report Toggle **AI Investigation Report** on for the monitor to enable automated analysis when the alert triggers. ### Investigation Prompt The **Prompt** field tells the AI what to look for while investigating the alert. This prompt gives the model operational context, guidance on related systems, and instructions for what the report should include. Use the prompt to describe things like: * Dependencies of the affected service * Related datasets, logs, traces, or systems to inspect * Relevant keys, fields, or metrics to compare * Expected baselines or time windows * The output you want in the report, such as impact, timeline, or likely cause Example prompt: > When investigating this error, check recent deployment logs, verify database connection pool status, and compare current resource usage with baseline metrics from the past 7 days. *** ## What The Report Can Include Based on the prompt and alert context, the resulting investigation report may include: * A likely diagnosis or root-cause hypothesis * Affected services, components, or users * A timeline of the issue * Related evidence gathered from your telemetry * Suggested next steps for responders The exact contents depend on the quality of the prompt and the telemetry available in Bronto. *** ## Writing Effective Prompts The strongest prompts are short, specific, and operationally grounded. Good prompts usually: * Name the service or workflow involved * Identify dependencies worth checking * Point to important datasets or fields * Ask for concrete outputs such as impact, timeline, or probable cause Avoid prompts that are too broad or generic. The goal is to guide the investigation, not document every troubleshooting step. *** ## When To Use It Use AI Investigation Reports when you want alert notifications to include an immediate starting point for triage, especially for: * Repeating production incidents * Monitors tied to a critical service or workflow * On-call handoffs where context is often missing * Alerts that require checking multiple related systems For event-level investigation started directly from the log viewer, see [BrontoScope](/ai-features/brontoscope). *** ## Limitations * Results depend on the data available to Bronto at the time the monitor fires * Better prompts produce better reports * AI-generated diagnoses are investigative guidance, not guaranteed root cause *** ## Related Pages * [Monitoring Overview & Threshold Monitors](/core-features/monitors) * [BrontoScope](/ai-features/brontoscope) # AI Overview Source: https://docs.bronto.io/ai-features/ai-welcome Connect AI agents and MCP clients to Bronto, run AI-driven investigations, and turn raw telemetry into structured, queryable observability data. Bronto gives you multiple ways to bring AI into your observability workflows — and to observe the AI your own applications run. Whether you want to connect an MCP client, run the server locally, investigate production issues with AI, instrument an LLM-powered application, or automatically structure raw telemetry, this section will help you get started. Connect Claude or another MCP-compatible client directly to Bronto’s hosted endpoint. No local server required. Install Bronto's Cursor plugin or Claude Code plugin workflows so coding agents understand Bronto MCP and logging tasks. Run the Bronto MCP server on your own machine with Python and connect it to Claude Code or another compatible agent. Automatically investigate events and issues with AI and get scope, likely causes, next steps, and supporting evidence in seconds. Attach AI-generated investigation reports to monitor alerts using a prompt that tells Bronto what to check. Capture prompts, responses, token usage, and model metadata from your own LLM-powered applications using the OpenTelemetry GenAI semantic conventions, and search them in Bronto. Use AI to turn unstructured telemetry into structured, queryable events with custom parsers tailored to your data. Build custom observability interfaces with tools like Lovable and v0 on top of Bronto APIs. ## What you can do Give agents access to datasets, keys, field values, search, and aggregated analysis workflows through MCP. Use BrontoScope to automatically assess impact, identify likely causes, and surface recommended next steps. Add AI Investigation Reports to monitors so alerts arrive with automated analysis and recommended follow-up. Start quickly with Hosted MCP, or choose Local MCP when you need more control over how the server runs. Instrument applications that call OpenAI, Anthropic, Amazon Bedrock, or LangChain with the OpenTelemetry GenAI semantic conventions and send that telemetry to Bronto. Create custom parsers that extract fields from application, system, and custom data formats so your data is easier to search and analyze. Use Bronto APIs to create workflow-specific dashboards, service maps, and operational views. ## Recommended workflows ### 1. Connect an agent to Bronto Start with one of the MCP options: * Choose **Hosted MCP** for the simplest setup * Choose **Local MCP** if you want to run the server yourself Managed by Bronto. Best for the fastest path to an MCP connection. Runs locally with Python. Best when you need control or a self-managed setup. ### 2. Investigate a production issue When you hit an unfamiliar issue, use BrontoScope to get an immediate starting point for your investigation. Ideal for quickly understanding impact, likely causes, and the next queries to run. ### 3. Add AI analysis to monitor alerts If you want investigations to run automatically when alerts fire, configure AI Investigation Reports on the monitor itself. Best for monitor-driven workflows where responders need a diagnosis attached to the alert. ### 4. Improve the quality of your data If your data is hard to search because it is unstructured, create a parser first. Transform raw telemetry into structured fields that are easier to search, group, and analyze. ### 5. Instrument an LLM-powered application If your own application calls an LLM — directly, via Amazon Bedrock/AgentCore, or through LangChain — capture that as GenAI telemetry rather than plain logs. Best for teams shipping LLM or agent features who want prompts, responses, token usage, and model metadata searchable in Bronto. # Amazon Bedrock AgentCore observability with OpenTelemetry Source: https://docs.bronto.io/ai-features/aws-agentcore Send OpenTelemetry logs, metrics, and traces from Amazon Bedrock AgentCore Runtime agents to Bronto, including agent-loop spans, token usage, and tool calls. This page covers capturing the telemetry an agent produces while running on the [Amazon Bedrock AgentCore](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/what-is-bedrock-agentcore.html) Runtime and sending it to Bronto. Where [Amazon Bedrock LLM observability](/ai-features/aws-bedrock) instruments a single `Converse` call, an agent on AgentCore runs a multi-step reasoning loop with tool calls — producing deep, nested traces following the [OpenTelemetry GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md). AgentCore, Strands, and the GenAI conventions evolve quickly. Commands and instrumentation behavior here were verified on **July 17, 2026** with `bedrock-agentcore-starter-toolkit`; AWS also offers a newer `agentcore-cli` with a different command set. For the broader ingestion picture (direct OTLP vs. a Collector, and where AgentCore fits among AWS services), see [Amazon Bedrock AgentCore Logs, Metrics and Traces](/integrations/aws-agentcore). For the attributes Bronto surfaces and how to search them, see [LLM Observability](/ai-features/llm-observability). This page uses Python with the [Strands](https://strandsagents.com/) agent framework, which emits GenAI spans through the tracer provider you configure. The same approach applies to any agent runtime: you disable AgentCore's managed telemetry pipeline and point the OpenTelemetry SDK at Bronto. ## How AgentCore observability works AgentCore Runtime ships with a **managed OpenTelemetry pipeline** (the AWS Distro for OpenTelemetry) that, by default, delivers agent telemetry to **Amazon CloudWatch** GenAI Observability. To send logs, metrics, and traces to Bronto instead, you **disable the managed pipeline** and configure the OpenTelemetry SDK inside your agent to export OTLP to Bronto through an OTel Collector (or, where you don't run one, directly). ## Prerequisites * Python 3.10 or later, and `pip` * An agent deployed to AgentCore Runtime (this guide uses the [Strands](https://strandsagents.com/) framework and the `bedrock-agentcore` SDK) * The AgentCore CLI: `pip install bedrock-agentcore-starter-toolkit` * A running OTel Collector configured to forward to Bronto — see [Connect OpenTelemetry to Bronto](/agent-setup/open-telemetry) or, on AWS, [ADOT](/integrations/aws-adot). AgentCore's managed public network mode must reach it over a public endpoint; a private VPC-only address is not reachable. Export [directly to Bronto](#direct-export-vs-a-collector) when you do not operate a public Collector endpoint. * A Bronto ingestion API key — held by the Collector, or sent as the `x-bronto-api-key` header when exporting directly. See [API Keys](/Account-Management/API-Keys) for how to create one with ingestion permissions. ## Disable the managed pipeline Two switches take AWS's managed observability out of the way so your own exporters own the signal: * At configure time, pass `--disable-otel`. * At runtime, set `DISABLE_ADOT_OBSERVABILITY=true` — passed to the deployed agent with `--env` (see [Configure OTLP export](#configure-otlp-export) below). ```bash theme={"dark"} agentcore configure -e agent.py -n my_agent -r eu-west-1 \ -rf requirements.txt --disable-otel --non-interactive ``` ## Install dependencies ```bash theme={"dark"} pip install \ opentelemetry-sdk \ opentelemetry-exporter-otlp-proto-http \ opentelemetry-instrumentation-botocore \ strands-agents strands-agents-tools \ bedrock-agentcore ``` ## Configure OTLP export Point the agent's OTLP exporters at your Collector, which holds the Bronto credential and forwards each signal to Bronto's per-signal endpoints. The agent runs in a managed container, so plain shell `export` only reaches it during local development — for the deployed runtime, pass the same variables with repeated `--env` flags on `agentcore deploy`: ```bash Deployed (agentcore deploy) theme={"dark"} # AgentCore public network mode needs an internet-reachable HTTPS endpoint, # such as ADOT on ECS behind a public ALB. Private VPC DNS won't work. agentcore deploy \ --env DISABLE_ADOT_OBSERVABILITY=true \ --env OTEL_EXPORTER_OTLP_ENDPOINT=https:// \ --env OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \ --env OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental,gen_ai_tool_definitions ``` ```bash Local development theme={"dark"} # localhost works here because the agent and the Collector # share your machine — a deployed agent cannot reach it. export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf export OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental,gen_ai_tool_definitions ``` `agentcore deploy --env` values are not automatically reused by a later deployment. Put every required telemetry flag in your deployment script and pass them on every redeploy, or the runtime can silently return to AWS's managed telemetry pipeline. Keeping the exporters pointed at a Collector keeps the agent code vendor-neutral and the Bronto API key out of the runtime config. If no Collector is reachable from the runtime, export straight to Bronto instead — see [Direct export vs. a Collector](#direct-export-vs-a-collector) below. Resource attributes such as `service.name` and `service.namespace` are set in code on a shared `Resource`, exactly as in the [standard Python setup](/opentelemetry/python#configure-the-environment). `StrandsTelemetry` accepts a pre-configured tracer provider carrying that `Resource`, so all three signals share one identity with no environment variables to keep in sync. For logs only, Bronto also maps these attributes to the dataset and collection; metrics and traces remain outside datasets and collections. Bootstrap the three signal providers at startup — **before** the agent framework or any instrumented library is imported: ```python telemetry.py theme={"dark"} import logging, os # Use the current Strands GenAI shape and include tool definitions. os.environ.setdefault( "OTEL_SEMCONV_STABILITY_OPT_IN", "gen_ai_latest_experimental,gen_ai_tool_definitions", ) from opentelemetry import metrics, trace from opentelemetry._logs import set_logger_provider from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter from opentelemetry.instrumentation.botocore import BotocoreInstrumentor from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler from opentelemetry.sdk._logs.export import BatchLogRecordProcessor from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter def setup_telemetry() -> None: # One Resource shared by logs, metrics, and traces — the same pattern as the # standard Python setup (/opentelemetry/python#configure-the-environment). resource = Resource.create({ "service.name": "my-agent", # shared service identity; log dataset "service.namespace": "agents", # shared namespace; log collection }) # Traces: hand Strands a tracer provider built on the shared resource. # Strands creates its spans from the *global* provider, and only registers # one itself when you don't pass your own — so set it globally here. tracer_provider = TracerProvider(resource=resource) trace.set_tracer_provider(tracer_provider) from strands.telemetry import StrandsTelemetry StrandsTelemetry(tracer_provider=tracer_provider).setup_otlp_exporter() # Logs: bridge Python logging so structured `extra=` fields arrive as # first-class, queryable attributes in Bronto. logger_provider = LoggerProvider(resource=resource) logger_provider.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter())) set_logger_provider(logger_provider) logging.getLogger().addHandler(LoggingHandler(logger_provider=logger_provider)) logging.getLogger().setLevel(logging.INFO) # Metrics: export instruments emitted by the application and its libraries. metric_reader = PeriodicExportingMetricReader(OTLPMetricExporter()) metrics.set_meter_provider( MeterProvider(resource=resource, metric_readers=[metric_reader]) ) # Trace the boto3 calls to AgentCore primitives (Memory, Code Interpreter, # Gateway) as child spans of the agent invocation. BotocoreInstrumentor().instrument() ``` Call `setup_telemetry()` at the very top of your entrypoint, before importing Strands: ```python agent.py theme={"dark"} from telemetry import setup_telemetry setup_telemetry() from bedrock_agentcore.runtime import BedrockAgentCoreApp from strands import Agent # ... ``` ## What you get on the trace A single agent invocation becomes one trace with nested spans: | Span | Source | Notes | | - | - | - | | Agent invocation / loop | Strands | Root span for the reasoning loop | | `chat` | Strands GenAI instrumentation | One per model call, carrying `gen_ai.*` attributes; the model id is an attribute | | Tool calls | Strands | One child span per tool the agent invokes | | AgentCore primitive calls | `BotocoreInstrumentor` | Memory, Code Interpreter, and Gateway (MCP) calls as child spans | Useful GenAI attributes on the model spans: | Attribute | Example | Notes | | - | - | - | | `gen_ai.request.model` | `eu.amazon.nova-pro-v1:0` | Requested model / inference profile | | `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens` | `412`, `173` | Token usage (numeric — chart and sum these) | | `gen_ai.operation.name` | `chat` | Operation type | | `gen_ai.response.finish_reasons.0` | `end_turn` | Why generation stopped | These are first-class, queryable fields in Bronto. See [LLM Observability](/ai-features/llm-observability) for the full recommended attribute set. Strands tool-call spans use standard attributes including `gen_ai.tool.name` and `gen_ai.tool.call.id`; exact coverage varies by Strands version. AgentCore-primitive spans from `BotocoreInstrumentor` (Memory, Code Interpreter, Gateway) instead carry AWS SDK attributes such as `rpc.method` and `aws.request_id`. Inspect a real trace before building version-sensitive dashboards. ## Capturing prompt, response, and tool IO Strands captures message content by default and does not use `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT`. To put content directly on span attributes for backends that cannot read OTel events, add `gen_ai_span_attributes_only` to `OTEL_SEMCONV_STABILITY_OPT_IN`. Treat this data as sensitive. You can also log each agent result as structured GenAI attributes: ```python theme={"dark"} import logging log = logging.getLogger(__name__) # after the agent produces its answer: log.info( "agent.result", extra={ "event.name": "agent.result", "gen_ai.request.model": model_id, "gen_ai.output.messages": response_text, # full response as a queryable field "session.id": session_id, }, ) ``` Avoid printf-style logging (`log.info("tokens=%s", n)`) for data you want to query — that produces a flat message string rather than structured fields. See [LLM Observability](/ai-features/llm-observability) for the recommended attribute names. ## Verify in Bronto Trigger an invocation of the deployed agent: ```bash theme={"dark"} agentcore invoke '{"prompt": "What is the weather in Dublin?"}' ``` **Traces** — open [Explore Traces](/tracing/explore-traces) and filter by your `service.name`. Open the newest trace and confirm the nesting from the table above: the agent loop at the root, a `chat` span per model call, and tool-call / AgentCore-primitive spans beneath it. **Logs** — open [Log Search](https://app.bronto.io/search) and filter by the same `service.name`. **Metrics** — open **Metric Explorer**, select a recently emitted metric, and confirm that it carries the same `service.name`. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). Bronto indexes log-record attributes with a `$` prefix. Query the structured fields by name — for example `"$event.name"` or `"$gen_ai.request.model"`. Because the searchable body of a structured event is the event name, search agent content with **field predicates** rather than full-text: ``` "$event.name" = 'agent.result' ``` ``` "$gen_ai.output.messages" ILIKE '%degraded%' ``` Token usage is numeric, so you can aggregate it — for example average output tokens per model, or total tokens over time — in aggregate views and [Visualizations](/Search-and-Visualize/Log-Visualization). ## Direct export vs. a Collector * **Via an OTel Collector** (recommended) — the agent exports OTLP to a Collector that holds the Bronto credential and forwards each signal. This keeps the agent code vendor-neutral, gives you a place to add processors / sampling / fan-out, and matches how Bronto ingests other AWS telemetry. See [Amazon Bedrock AgentCore Logs, Metrics and Traces](/integrations/aws-agentcore) and [ADOT](/integrations/aws-adot). * **Direct OTLP to Bronto** — when no Collector is reachable from the runtime, or for short-lived jobs: set `OTEL_EXPORTER_OTLP_ENDPOINT` to the Bronto ingestion base (EU `https://ingestion.eu.bronto.io`, US `https://ingestion.us.bronto.io`) and add your [API key](/Account-Management/API-Keys) as the `x-bronto-api-key` header. No Collector, VPC, or sidecar required. ```bash theme={"dark"} agentcore deploy \ --env DISABLE_ADOT_OBSERVABILITY=true \ --env OTEL_EXPORTER_OTLP_ENDPOINT=https://ingestion.eu.bronto.io \ --env OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \ --env OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=" ``` ## References * [Amazon Bedrock AgentCore Logs, Metrics and Traces](/integrations/aws-agentcore) * [Amazon Bedrock LLM observability](/ai-features/aws-bedrock) * [LLM Observability](/ai-features/llm-observability) * [Amazon Bedrock AgentCore documentation](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/what-is-bedrock-agentcore.html) * [OpenTelemetry GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) # Amazon Bedrock LLM observability with OpenTelemetry Source: https://docs.bronto.io/ai-features/aws-bedrock Capture token usage, model metadata, and prompt/response content from Amazon Bedrock calls with OpenTelemetry GenAI auto-instrumentation in Bronto. This page covers instrumenting an application that calls the Amazon Bedrock `Converse` / `InvokeModel` APIs so that GenAI telemetry — token usage, model, latency, finish reason, and prompt/response content — flows to Bronto following the [OpenTelemetry GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/aws-bedrock.md). The conventions and instrumentation are in active development. This page was verified on **July 17, 2026**. For the broader ingestion picture (the Collector and where Bedrock fits among AWS services), see [Amazon Bedrock Logs, Metrics and Traces](/integrations/aws-bedrock). For the attributes Bronto surfaces and how to search them, see [LLM Observability](/ai-features/llm-observability). ## Prerequisites * Python 3.9 or later, and `pip` * An application that calls Amazon Bedrock via `boto3` (the `bedrock-runtime` client) * A running OTel Collector configured to forward to Bronto — see [Connect OpenTelemetry to Bronto](/agent-setup/open-telemetry) or, on AWS, [ADOT](/integrations/aws-adot) ## Install dependencies ```bash theme={"dark"} pip install \ opentelemetry-sdk \ opentelemetry-exporter-otlp-proto-http \ opentelemetry-instrumentation-botocore \ boto3 ``` **Version matters for Bedrock.** The Bedrock GenAI extension lives in `opentelemetry-instrumentation-botocore`, and it was added relatively recently. Older releases (for example `0.50b0`) ship **no Bedrock extension at all** — Bedrock calls are then traced only as generic AWS API spans (`rpc.system`, `rpc.method=Converse`, `aws.request_id`) with **no token usage, model, or prompt/response**. If your traces are missing GenAI data, this is almost always the cause. Use `opentelemetry-instrumentation-botocore>=0.55b0`; this guide was validated with `0.64b0` and `opentelemetry-sdk==1.43.0`. ## Enable Bedrock GenAI instrumentation The botocore instrumentation patches the `bedrock-runtime` client automatically. To include message content in its trace-correlated log events, set this before instrumentation starts: ```bash theme={"dark"} # Capture prompt and response content (off by default) export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true ``` Instrument either with the zero-code wrapper: ```bash theme={"dark"} opentelemetry-instrument python app.py ``` …or programmatically at startup (set the environment variables **before** this runs): ```python instrument.py theme={"dark"} from opentelemetry.instrumentation.botocore import BotocoreInstrumentor BotocoreInstrumentor().instrument() ``` With this in place, recognized Bedrock models produce a client span named like `chat ` carrying GenAI attributes. Unrecognized or newly introduced inference-profile IDs can retain the generic `Bedrock Runtime.Converse` name; inspect the attributes rather than relying only on the span name. ## What you get on the span Botocore `0.64b0` emits the following span attributes when the corresponding value is available: | Attribute | Example | Notes | | - | - | - | | `gen_ai.system` | `aws.bedrock` | Provider identifier emitted by this botocore release | | `gen_ai.operation.name` | `chat` | `chat` for most calls; `text_completion` for Amazon Titan text completion via `InvokeModel` | | `gen_ai.request.model` | `eu.amazon.nova-micro-v1:0` | Requested model or inference-profile ID | | `gen_ai.request.max_tokens` | `512` | Maximum output tokens requested | | `gen_ai.request.temperature` | `0.7` | Sampling temperature | | `gen_ai.request.top_p` | `0.9` | Top-p sampling value | | `gen_ai.request.stop_sequences` | `["END"]` | Array of requested stop sequences | | `gen_ai.usage.input_tokens` | `9` | Input tokens reported by Bedrock; estimated for some model-specific `InvokeModel` responses | | `gen_ai.usage.output_tokens` | `36` | Output tokens reported by Bedrock; estimated for some model-specific `InvokeModel` responses | | `gen_ai.response.finish_reasons` | `["end_turn"]` | Array containing the response stop reason | | `server.address` | `bedrock-runtime.eu-west-1.amazonaws.com` | Bedrock Runtime endpoint | | `server.port` | `443` | Endpoint port | | `error.type` | `ValidationException` | Present when the operation ends with an error | The span is a `CLIENT` span and is normally named `chat ` or `text_completion `. Request parameters, usage, and finish reason are conditional: botocore omits a field when the request or selected model does not expose it. The general-purpose `BotocoreInstrumentor` also adds AWS SDK attributes such as `rpc.system = aws-api`, `rpc.method`, `rpc.service`, and `aws.request_id`. The request ID is useful for correlating the span with CloudTrail and other AWS-side logs. Inspect a real span with a Collector `debug` exporter or a local `ConsoleSpanExporter` before relying on version-sensitive AWS attributes. ## Metrics emitted by botocore When an OpenTelemetry meter provider is configured, the same instrumentation emits: | Metric | Unit | Dimensions | | - | - | - | | `gen_ai.client.operation.duration` | Seconds | `gen_ai.system`, `gen_ai.operation.name`, `gen_ai.request.model`, `server.address`, `server.port`, and `error.type` on failures | | `gen_ai.client.token.usage` | Tokens | The same dimensions plus `gen_ai.token.type` to distinguish input and completion tokens | ## Capture input and output content ### Automatic content events Botocore `0.64b0` records messages as trace-correlated OTel log events rather than `gen_ai.input.messages` / `gen_ai.output.messages` span attributes. Depending on the request, it emits `gen_ai.system.message`, `gen_ai.user.message`, `gen_ai.assistant.message`, `gen_ai.tool.message`, and `gen_ai.choice`. With content capture disabled, these events can still be emitted but their message bodies are empty. Prompts, responses, system instructions, and tool data can contain sensitive information. Enable content capture only after applying appropriate access controls, redaction, and retention policies. ### Put input messages on the Bedrock span If you need the current `gen_ai.input.messages` field directly on the botocore-created Bedrock client span, add a `request_hook`. The hook runs while that span is active. Use this setup instead of the basic `BotocoreInstrumentor().instrument()` call above. This example normalizes text messages sent through `Converse` or `ConverseStream` and stores the structured value as JSON: ```python theme={"dark"} import json from opentelemetry.instrumentation.botocore import BotocoreInstrumentor def bedrock_request_hook(span, service_name, operation_name, api_params): if service_name != "bedrock-runtime" or operation_name not in { "Converse", "ConverseStream", }: return messages = [] for message in api_params.get("messages", []): parts = [ {"type": "text", "content": block["text"]} for block in message.get("content", []) if "text" in block ] messages.append({"role": message["role"], "parts": parts}) if messages: span.set_attribute("gen_ai.input.messages", json.dumps(messages)) BotocoreInstrumentor().instrument(request_hook=bedrock_request_hook) ``` Extend the normalizer if your requests include images, documents, tool calls, or tool results. `InvokeModel` request bodies are provider-specific and require model-specific parsing. Botocore already records generated output in the `gen_ai.choice` content event. An application can additionally add `gen_ai.output.messages` to an enclosing application span or a structured log after the response has been consumed. This is often simpler for streaming responses, because their final output is not available when the initial botocore response hook runs. ## Verify in Bronto After running your application, open [Log Search](https://app.bronto.io/search) and filter by the `service.name` you set on your resource. Find all Bedrock spans emitted by botocore: ```sql theme={"dark"} "$gen_ai.system" = 'aws.bedrock' ``` Find calls to a particular model or inference profile: ```sql theme={"dark"} "$gen_ai.system" = 'aws.bedrock' AND "$gen_ai.request.model" = 'eu.amazon.nova-micro-v1:0' ``` Find calls that stopped because the model completed its turn. Botocore emits an array on the span; Bronto indexes its first element as `.0`: ```sql theme={"dark"} "$gen_ai.response.finish_reasons.0" = 'end_turn' ``` Find unusually large responses: ```sql theme={"dark"} "$gen_ai.usage.output_tokens" > 1000 ``` For captured request content, search the structured body of the emitted user-message event: ```sql theme={"dark"} "$event.name" = 'gen_ai.user.message' AND "$content.0.text" ILIKE '%refund%' ``` For captured response content, search the choice event: ```sql theme={"dark"} "$event.name" = 'gen_ai.choice' AND "$message.content.0.text" ILIKE '%refund approved%' ``` If you installed the request hook above, search the input attribute on the Bedrock span directly: ```sql theme={"dark"} "$gen_ai.input.messages" ILIKE '%refund%' ``` In aggregate views, select **Sum**, **Average**, **Median**, or a percentile for `$gen_ai.usage.input_tokens` or `$gen_ai.usage.output_tokens`, then group by `$gen_ai.request.model`. This compares token usage across Bedrock models using fields botocore emits today. See [Visualizations](/Search-and-Visualize/Log-Visualization) for dashboard options. ## Direct export to Bronto If you are not running a Collector (for local development or short-lived jobs), export OTLP straight to Bronto by adding your API key. See the [direct export section](/opentelemetry/python#direct-export-to-bronto) on the Python page; point the exporters at the Bronto ingestion endpoints: | Region | Traces endpoint | Logs endpoint | Metrics endpoint | | - | - | - | - | | EU | `https://ingestion.eu.bronto.io/v1/traces` | `https://ingestion.eu.bronto.io/v1/logs` | `https://ingestion.eu.bronto.io/v1/metrics` | | US | `https://ingestion.us.bronto.io/v1/traces` | `https://ingestion.us.bronto.io/v1/logs` | `https://ingestion.us.bronto.io/v1/metrics` | Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). ## References * [Amazon Bedrock Logs, Metrics and Traces](/integrations/aws-bedrock) * [LLM Observability](/ai-features/llm-observability) * [Semantic conventions for AWS Bedrock](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/aws-bedrock.md) * [opentelemetry-instrumentation-botocore](https://pypi.org/project/opentelemetry-instrumentation-botocore/) # AWS DevOps Agent Integration Source: https://docs.bronto.io/ai-features/aws-devops-agent Register Bronto's hosted MCP server with the AWS DevOps Agent so it can search your Bronto logs while investigating and operating workloads in AWS. ## Overview The [AWS DevOps Agent](https://aws.amazon.com/) is an AI assistant for operating AWS workloads. By registering Bronto's hosted MCP server as a **Capability Provider**, the DevOps Agent can search your Bronto **log datasets** and call Bronto's time-series and schema-discovery tools while it investigates issues — grounding its reasoning in your actual log data instead of just AWS service state. Metrics and traces are not stored in datasets or collections; view them in Bronto's Metric Explorer and Explore Traces. This page walks through registering the Bronto MCP server in the AWS DevOps Agent console using API-key authentication. For the underlying AWS workflow, see the [AWS documentation on connecting MCP servers](https://docs.aws.amazon.com/devopsagent/latest/userguide/configuring-capabilities-for-aws-devops-agent-connecting-mcp-servers.html). ## Prerequisites * A Bronto account with data being ingested. If you haven't sent data yet, [set up an agent](/agent-setup/agent-intro) first. * A Bronto API key with search permissions. See [API Keys](/Account-Management/API-Keys). * Access to the AWS DevOps Agent in your AWS account, with permission to register Capability Providers. * The Bronto hosted MCP endpoint for your region — see [Hosted MCP Server](/ai-features/hosted-mcp). | Region | Hosted MCP Endpoint URL | | - | - | | US | `https://mcp.us.bronto.io/mcp` | | EU | `https://mcp.eu.bronto.io/mcp` | ## Register the Bronto MCP server In the AWS DevOps Agent console, open **Capability Providers** and start the **Register MCP Server** flow. Enter the server details: | Field | Value | | - | - | | **Name** | `BrontoMCPServer` (or any name you prefer) | | **Endpoint URL** | The hosted MCP endpoint for your region (see above) | | **Description** | Optional | Bronto's hosted MCP server implements the **Streamable HTTP** transport, which is what the DevOps Agent requires. AWS DevOps Agent — MCP server details step with the Bronto endpoint URL Click **Next**. Select **API Key** as the authorization flow. The Bronto hosted MCP server authenticates incoming requests via a static API-key header, so this is the correct option — not OAuth or AWS SigV4. AWS DevOps Agent — Authorization Flow step with API Key selected Click **Next**. Enter the API-key configuration that Bronto expects: | Field | Value | | - | - | | **API Key Name** | `BrontoAPIKey` (display name only) | | **API Key Header** | `X-BRONTO-API-KEY` | | **API Key Value** | Your Bronto API key | AWS DevOps Agent — Authorization Configuration step with the Bronto API key header The header name **must** be `X-BRONTO-API-KEY` — Bronto's MCP server reads the API key from this header and will reject requests sent under any other header name. Click **Next**. Confirm the MCP server details and authorization configuration, then click **Add**. AWS DevOps Agent — Review and submit step showing the Bronto MCP server configuration ## Select MCP server tools After registration, the DevOps Agent prompts you to choose which Bronto tools it is allowed to call. The Bronto hosted MCP server exposes a set of read-only tools that cover log schema discovery, log search, time-series analysis over log data, and saved searches. These dataset tools do not query metrics or traces. AWS DevOps Agent — Select MCP server tools, showing all eight Bronto tools The recommended setup is to enable **all** Bronto tools. They are all read-only and cooperative — for example, the agent typically uses `get_datasets` and `get_keys` to discover the right dataset and schema before issuing a `search_logs` or `timeseries` query. For full descriptions of each tool, see [Hosted MCP Server — Capabilities](/ai-features/hosted-mcp#capabilities). As shown in the AWS UI, only enable MCP tools that are **read-only**. All Bronto tools listed here are read-only — they query log data and metadata without modifying anything in your Bronto account. Click **Save** to finish. ## Verify the connection Open an Agent Space in the AWS DevOps Agent console and ask a question that requires Bronto data, for example: ``` List the datasets I have in Bronto. ``` The agent should call `get_datasets` against the Bronto MCP server and return the datasets in your account. AWS DevOps Agent successfully calling the Bronto Get Datasets tool and returning a breakdown of datasets Once that works, you can move on to investigation-style prompts — searching recent error logs or comparing time windows. See [Hosted MCP Server — Example Prompts](/ai-features/hosted-mcp#example-prompts) for inspiration. ## Example use cases Once the Bronto Capability Provider is attached to an Agent Space, the DevOps Agent can combine AWS service state with Bronto telemetry in a single investigation. A few common workflows: ### Root-cause a service incident with log context When a service is misbehaving — elevated errors, failing health checks, customer reports, or a triggered alert — the agent can identify the affected resource in AWS and then call `search_logs` against the Bronto dataset for that service to surface the errors driving the incident. That includes stack traces, request IDs, and downstream-dependency failures that aren't visible from AWS service state alone. ### Investigate latency regressions in access logs Ask the agent to compare request-duration fields in your log datasets with a baseline window using `timeseries`, then drill into the slowest log events with `search_logs`. Use Bronto's Explore Traces page when the investigation requires span-level trace data. ### Correlate deployments with error spikes Point the agent at a recent ECS, EKS, or Lambda deployment and ask whether errors increased after the rollout. The agent uses AWS to identify the deploy window and Bronto to count and sample errors before and after — giving you a quick verdict on whether to roll back. ### Diagnose noisy or failing AWS Lambda functions For a specific Lambda function, the agent can fetch recent invocations from AWS and then call `search_logs` with the function name as a filter to summarise the dominant error patterns. Useful when a function is silently retrying, timing out, or hitting a downstream rate limit. ### Investigate elevated 5xx responses behind ALB or API Gateway Combine AWS ALB or API Gateway metrics with Bronto access logs to find the host, path, and upstream service driving a 5xx spike. The agent can use `get_keys` to discover the right fields in your dataset before grouping and filtering — without you having to remember the schema. ### Follow a request through correlated logs When you have a request ID, trace ID, or user ID from an AWS support case, ask the agent to find related log events in Bronto. The agent searches log datasets to assemble a timeline from correlated logs. To inspect the spans in a distributed trace, open Explore Traces in Bronto. ## Troubleshooting **Authentication errors when the agent calls Bronto.** Double-check that the API Key Header is exactly `X-BRONTO-API-KEY` and that the API key value is valid and has search permissions. Also confirm you registered the endpoint for the correct region (US vs EU) — a mismatched region returns an authentication error. **The agent does not call Bronto tools.** Confirm the tools were enabled on the **Select MCP server tools** step, and that the Bronto Capability Provider is attached to the Agent Space where you are prompting from. # Bronto Agent Skills Source: https://docs.bronto.io/ai-features/bronto-agent-skills Install Bronto's agent skills and plugins for Cursor or Claude Code so coding agents can investigate telemetry and improve logging workflows. Bronto Agent Skills is a GitHub repository that packages Bronto-specific instructions and plugin metadata for AI coding assistants. Use it when you want an agent to understand Bronto's MCP tools, investigate log datasets from your editor, or run Bronto's Claude Code logging workflow. Metrics and traces are viewed in their dedicated Bronto explorers rather than through dataset search. The Cursor plugin and Claude Code plugin currently solve different jobs. The Cursor plugin installs the Bronto MCP configuration and Bronto investigation skill. The Claude Code marketplace plugin currently provides the `bronto-logging` workflow for adding stable statement IDs to logging calls. Repository: ```text theme={"dark"} https://github.com/brontoio/bronto-agent-skills ``` ## What's included Teaches an agent how to use Bronto MCP for log-dataset discovery, schema inspection, timeseries analysis, raw log search, trace IDs, latency, and production debugging. Bundles the Bronto hosted MCP server configuration for US and EU regions with the Bronto investigation skill. Adds the `bronto-logging` Claude Code plugin, including a statement ID supervisor skill and worker agent for updating logging calls across a codebase. Defines hosted MCP endpoints for `bronto-us` and `bronto-eu`. OAuth is the default, with regional API keys available as an optional alternative. ## Before you start You need: * A Bronto account in the correct data region, US or EU * MCP access enabled by a Bronto administrator under **Settings → Authentication** * Optionally, a Bronto API key if you prefer API-key authentication to OAuth * Cursor or Claude Code, depending on the workflow you are setting up If you choose API-key authentication, create or manage keys in [API Keys](../Account-Management/API-Keys). Use the MCP endpoint that matches your Bronto organization: | Region | Hosted MCP endpoint | | - | - | | US | `https://mcp.us.bronto.io/mcp` | | EU | `https://mcp.eu.bronto.io/mcp` | ## Use with Cursor The Cursor plugin is the most direct way to use this repository for Bronto telemetry investigation from an IDE. It installs: * `mcp.json` with `bronto-us` and `bronto-eu` hosted MCP servers * `skills/bronto/SKILL.md`, which tells the agent how to investigate Bronto telemetry * Reference material for query shapes, MCP tool order, and investigation patterns The plugin is also listed in the [Cursor Plugin Directory](https://cursor.directory/plugins/bronto). See the [Cursor plugin README](https://github.com/brontoio/bronto-agent-skills/tree/main/.cursor-plugin) for the latest installation and configuration details. Start the Cursor Agent CLI with `agent`, run: ```text theme={"dark"} /plugin ``` Paste `https://github.com/brontoio/bronto-agent-skills.git` into plugin search, then install it at user or project scope. Open **Customize → MCPs**, select `bronto-us` or `bronto-eu` for your organization's region, then select **Login** and complete the browser authentication flow. Disable the unused regional server. If you do not want to use OAuth, open the installed Bronto plugin in **Customize**, select **Configure**, and set `US_BRONTO_API_KEY` or `EU_BRONTO_API_KEY` for your organization's region. Run **Developer: Reload Window** from the command palette. Open Cursor's MCP status and confirm that either `bronto-us` or `bronto-eu` is connected. Disable or ignore the region you do not use. Try a prompt like: ```text theme={"dark"} Use Bronto to list the datasets available in this organization, then show the keys for the production API logs. ``` ## Use with Claude Code There are two Claude Code paths, depending on what you want to do. ### Investigate Bronto telemetry For telemetry investigation in Claude Code, connect Claude directly to Bronto's hosted MCP endpoint. ```bash theme={"dark"} claude mcp add --transport http bronto https://mcp.eu.bronto.io/mcp ``` Use the US endpoint instead if your Bronto account is hosted in the US: ```bash theme={"dark"} claude mcp add --transport http bronto https://mcp.us.bronto.io/mcp ``` Then run: ```text theme={"dark"} /mcp ``` Select Bronto and complete the authentication flow. See [Hosted MCP Server](./hosted-mcp) for the full setup guide. ### Use the Claude Code logging plugin The Claude Code marketplace in `bronto-agent-skills` exposes the `bronto-logging` plugin. Use it when you want Claude Code to add or update stable `stmt_id` values on logging statements across a codebase. ```text theme={"dark"} /plugin ``` Choose **Add Marketplace**, then enter: ```text theme={"dark"} brontoio/bronto-agent-skills ``` Go to **Manage and uninstall plugins**, select **bronto-claude-code-plugins**, then enable **bronto-logging**. Ask Claude Code to add statement IDs to logging calls in a directory: ```text theme={"dark"} Use the Bronto logging plugin to add stable statement IDs to logging calls under src/. ``` The plugin discovers logging calls, dispatches worker agents by file, and merges the generated mapping into `statementIds.json`. ## How the Bronto investigation skill works The Bronto skill gives agents a repeatable query workflow: 1. Discover datasets with `get_datasets` or `get_datasets_by_name`. 2. Inspect fields with `get_keys`. 3. Inspect useful dimensions with `get_key_values`. 4. Use `timeseries` first for counts, rates, percentiles, group-bys, regressions, and top offenders. 5. Use `search_logs` for representative raw examples, exact trace IDs, event IDs, pasted errors, and payload drill-down. This prevents the agent from guessing field names, querying every dataset, or jumping straight to raw logs before it has an aggregate view. ## Verify the setup After installing either integration, ask the agent: ```text theme={"dark"} List the Bronto datasets I can access, then show the available keys for one production dataset. ``` A working setup should return dataset names, collections, dataset IDs, and field names from the correct Bronto region. If authentication fails, check: * You are using the endpoint for the correct Bronto region * The matching regional API key is configured if using API-key auth * MCP login is enabled in Bronto if using OAuth * Cursor third-party plugins, skills, and configs are enabled if using Cursor # BrontoScope Source: https://docs.bronto.io/ai-features/brontoscope Investigate error events automatically with BrontoScope, an AI-powered tool that identifies scope, root causes, and next steps without writing queries. BrontoScope enables **automatic AI-powered error investigation** directly from your logs. Instead of manually querying and correlating data, BrontoScope analyzes error events for you and delivers a structured report in seconds. No prompts. No setup. Just click and investigate. *** ## Overview When you encounter an error event in your logs, BrontoScope can: * Analyze the event across multiple dimensions * Correlate signals from logs, services, and infrastructure * Identify patterns and anomalies * Generate a clear, actionable report All in **under 10 seconds**. *** ## How It Works 1. Navigate to your logs and locate an error event 2. Click the event to open the **event panel** 3. Select **Investigate with AI** 4. BrontoScope automatically runs a multi-step analysis 5. Review the generated report and supporting data *** ## What BrontoScope Analyzes ### 1. Problem Scope BrontoScope determines the full impact of the error, including: * When the issue started * Whether the issue is ongoing or resolved * Affected: * Users * Services * Hosts * Regions (if applicable) This helps you quickly understand **blast radius and urgency**. *** ### 2. Likely Causes The AI evaluates patterns and correlations to suggest potential root causes, such as: * Network instability or latency spikes * Sudden traffic increases or load imbalance * Recent deployments or configuration changes * Application-level bugs or exceptions These insights are **hypothesis-driven**, not guesses — each is backed by observed data patterns. *** ### 3. Recommended Next Steps BrontoScope provides actionable guidance to move forward, including: * Suggested queries to run * Services or systems to inspect * Metrics to validate * Additional logs or time windows to review This reduces time-to-resolution by guiding your investigation. *** ### 4. Supporting Evidence Every conclusion is backed by transparent data: * Underlying queries executed by the AI * Relevant log samples * Generated charts and trends * Time-based comparisons You can **validate, refine, or extend** the investigation at any time. *** ## Key Benefits ### No Prompt Required BrontoScope requires **zero input from the user**. It: * Understands the context of the selected error * Determines relevant queries automatically * Executes a full investigation workflow *** ### Fast Time to Insight * Results delivered in **under 10 seconds** * Eliminates manual querying and correlation * Reduces mean time to detection (MTTD) and resolution (MTTR) *** ### Explainable AI Unlike black-box systems, BrontoScope shows: * How conclusions were reached * What data was used * Which queries were executed This ensures **trust and auditability**. *** ## When to Use BrontoScope Use BrontoScope whenever you: * Encounter a new or unfamiliar error * Need to quickly assess impact * Want to validate whether an issue is widespread * Are debugging production incidents * Need a starting point for deeper investigation *** ## Best Practices * Start with the **first occurrence** of an error for cleaner insights * Compare multiple investigations if the issue evolves over time * Use the generated queries to drill deeper into specific hypotheses * Combine with dashboards and alerts for full observability coverage *** ## Limitations * Results depend on available log and telemetry data * AI-generated causes are **probabilistic**, not guaranteed root causes * Complex multi-system failures may require further manual investigation *** ## Summary BrontoScope transforms error investigation from a manual, time-consuming process into an **instant, AI-driven workflow**. By combining automated analysis, clear explanations, and actionable insights, it enables teams to: * Detect issues faster * Understand impact immediately * Resolve incidents more efficiently # Hosted MCP Server Source: https://docs.bronto.io/ai-features/hosted-mcp Connect Claude and other MCP clients to Bronto's hosted MCP endpoint to query log data, no local server required, using your existing Bronto login. Hosted MCP is available to all Bronto accounts. MCP access is governed by the same login controls used across the rest of the product. ## Overview Bronto now supports a **hosted MCP experience**. Instead of running an MCP server yourself, you can enable MCP access directly in the Bronto UI, sign in with your existing Bronto login method (OAuth, SSO, or Google Social), and connect supported MCP clients to Bronto's hosted MCP endpoint. This makes the setup feel much closer to connecting any other SaaS integration than bootstrapping local developer infrastructure. User and access management for MCP is identical to any other access to your Bronto account. *** ## Enabling MCP in the UI The first step is to enable MCP access inside Bronto. Hosted MCP access is intentionally tied to the same login controls used by the rest of the product — if a login method is not enabled for MCP, authorization requests using that method will be rejected. This gives admins a clear, centralised way to control: * Whether MCP access is allowed at all * Which login methods are valid for MCP * Which users can successfully complete the MCP OAuth flow Navigate to **Settings → Authentication** in the Bronto UI. You will see the MCP login method listed as an available option on this page. Toggle the MCP login method to **Enabled**. Click **Configure** on the MCP card to open the configuration panel. Review the available SSO providers and any other supported login methods that should be permitted for MCP access. Click **Save** to apply the configuration. MCP access is now enabled for the selected login methods. *** ## Connecting an MCP Client Once MCP is enabled in the UI, client setup is significantly simpler than the local-server approach. Instead of pointing the client at a locally running process, you configure it to use Bronto's hosted MCP endpoint. The client then performs the standard OAuth flow. Open a terminal and run the following command to register the Bronto MCP server and launch Claude CLI: ```bash theme={"dark"} claude mcp add --transport http bronto https://mcp.eu.bronto.io/mcp && claude ``` Once Claude CLI is open, enter the following command: ``` /mcp ``` Select **Bronto** from the list and press **Enter** to open the MCP authentication flow. ``` ────────────────────────────────────── Manage MCP servers 1 servers Local MCPs ❯ bronto · △ needs authentication ``` In Claude Desktop or Claude Web, go to **Settings → Connectors** and select **Add custom connector**. Enter a name for the connector, then provide the hosted MCP endpoint URL for the region where your Bronto account is located: | Region | MCP Endpoint URL | | - | - | | US | `https://mcp.us.bronto.io/mcp` | | EU | `https://mcp.eu.bronto.io/mcp` | Select the **Connect** button beside the Bronto MCP entry in the connectors list to open the authentication flow. *** ## Authentication Flow After adding the connection, you must authenticate with Bronto. The flow is the same regardless of which client you use. Your MCP client opens the Bronto MCP authorization URL in a browser window. Sign in using an allowed Bronto login method — OAuth, SSO, or Google Social, whichever has been enabled for MCP by your admin. Review and approve the requested permission scopes. Bronto redirects back to your MCP client and issues an access token. Your client is now connected. The authentication flow mirrors the standard OAuth 2.0 pattern. Once connected, token refresh is handled automatically by the client. *** ## API Key Access The hosted MCP endpoint also supports **API key-based access** for clients that can send custom headers directly. This is useful when an MCP client only supports local stdio servers but you want to connect it to a remote hosted endpoint. ### Using mcp-remote [mcp-remote](https://www.npmjs.com/package/mcp-remote) is a bridge utility that translates stdio-based MCP clients to remote HTTP endpoints with support for custom auth headers. ```json theme={"dark"} { "mcpServers": { "bronto-eu": { "command": "npx", "args": [ "mcp-remote", "https://mcp.eu.bronto.io/mcp", "--header", "X-BRONTO-API-KEY:${AUTH_TOKEN}" ], "env": { "AUTH_TOKEN": "" } } } } ``` Never hardcode your API key directly in configuration files that may be committed to version control. Use environment variables as shown above. ### Direct Header Attachment For clients that support `streamable-http` transport and custom headers natively, such as [Kiro](https://kiro.dev/), you can attach the API key header directly without mcp-remote: ```json theme={"dark"} { "mcpServers": { "bronto-us": { "type": "streamable-http", "url": "https://mcp.us.bronto.io/mcp", "headers": { "Accept": "application/json, text/event-stream", "X-BRONTO-API-KEY": "" }, "autoApprove": [], "disabled": false } } } ``` *** ## Endpoint Reference | Region | Hosted MCP Endpoint URL | | - | - | | US | `https://mcp.us.bronto.io/mcp` | | EU | `https://mcp.eu.bronto.io/mcp` | Use the endpoint that matches the data region where your Bronto account is hosted. Connecting to the wrong region will result in an authentication error. *** ## Capabilities The Bronto hosted MCP server exposes a set of tools to connected clients, covering the full workflow: discover schema, search and aggregate log data, save and re-run queries, manage alerting monitors, and audit coverage and usage. A typical investigation moves through these in sequence: use `get_datasets` to identify the right data source, `get_keys` to understand its schema, `get_key_values` to build precise filters, then `search_logs` for raw event investigation or `timeseries` for aggregated trend analysis. From there you can preserve a query as a saved search, turn a finding into a monitor, and check where you have coverage or blind spots. ### Discovery & search Returns the available field names for every dataset you can access. Use this to quickly understand the schema across all datasets before running searches or aggregations. Lists all available datasets, including each dataset's name, collection, unique dataset ID, and tags. Use this when you need to discover what data sources are available. Finds datasets by exact dataset name and collection name. Use this when you know the dataset you want and need its metadata or dataset ID. Returns the available values for a specific field in a specific dataset. Use this to discover common field values and build more precise filters. Returns the available field names for a specific dataset. Use this to inspect a dataset's schema before querying it. Searches raw log events in one or more datasets over a time range. Supports dataset IDs or a dataset selection expression, optional filters, result limits, and sorting. Best for investigations and event-level troubleshooting. Computes aggregated metrics and time-series trends from log data. Supports COUNT, SUM, AVG, percentile calculations, grouping, time bucketing, and comparison windows. Best for summaries and trend analysis. ### Saved searches Lists and reads saved searches, with optional filtering by text, tag, or field. Use this to discover existing saved searches before creating a new one. Creates one or more saved searches. As well as the query, it can set how the saved search renders — list, timeseries, table, top-list, pie, treemap, or a geomap of values by country. Supports batch creation. Executes a saved search by id and returns its results, identical to running the query directly. Optionally run it over a different time window. ### Monitors & coverage Finds existing monitors and, for a given monitor, its recent trigger and recovery history. Useful for retrospectives and avoiding duplicate alerts. Creates monitors (always muted for review before they can alert). Supports threshold and no-data alerting (fire when a log goes quiet) and an investigation prompt that Bronto runs automatically when the monitor fires. Health-checks your existing monitors by re-running each backing query, so you can spot alarms that have silently broken or stopped receiving data. Reports, per dataset, whether it is monitored, searched, and still ingesting — surfacing blind spots such as a live dataset with no alert watching it. ### Usage & health Returns org-wide error and warning totals with a per-dataset breakdown. Precomputed, so it costs no search quota to run. Reports per-dataset ingestion and search usage against your monthly limits, and whether each dataset is actively ingesting or dormant. *** ## Example Prompts The best hosted MCP workflows start with dataset discovery, narrow the search space, then ask focused operational questions. CDN logs are a strong example: high-volume, operationally important, and often the first place teams look when users report latency, origin instability, or unusual traffic. The following prompts demonstrate useful fault-finding and analysis workflows using Claude and Opus 4.6. ### Example 1 — Find the right CDN datasets ``` Which datasets contain production CDN logs for our edge or delivery layer? ``` Teams often have multiple CDN-related datasets with non-obvious names, causing delays while users search for the right sources or query more than they need to. The hosted MCP server identifies likely datasets first, then surfaces log IDs, collections, and tags needed to scope all later queries correctly. The result should immediately surface the production CDN and edge-layer datasets in your account — confirming which datasets are actually carrying production CDN traffic before any deeper analysis begins. ### Example 2 — Look for elevated error responses ``` In the last 30 minutes, look through our CDN logs for elevated 5xx responses and group them by host, path, and status code. ``` **What to look for in CDN logs:** * Spikes in 5xx status codes * Concentration on a single hostname, service, or path * Whether failures are broad or isolated * Whether only a subset of POPs or edge nodes are affected This is one of the fastest ways to distinguish between a widespread origin issue, a bad deploy affecting one route, a customer-specific path problem, or low-impact isolated errors. ### Example 3 — Investigate latency regressions ``` Compare CDN response-time metrics for the last hour against the previous hour and identify the hosts or paths with the largest regression. ``` **What to look for in CDN logs:** * Increases in origin time or total response time * Regressions concentrated on one host or endpoint * Whether the issue appears at the edge or upstream * Whether the timing aligns with a deploy or traffic change This is especially useful when users report the site feeling slower but there is no obvious outage. The workflow makes it straightforward to compare time windows, identify the worst regressions, and narrow quickly to the hosts and paths driving the slowdown. ### Example 4 — Look for cache effectiveness problems ``` Search our CDN logs for cache-related fields and show whether cache miss rates increased in the last 24 hours. ``` **What to look for in CDN logs:** * Cache hit vs miss patterns * Sudden increases in origin fetches * Path prefixes with poor cache efficiency * Changes following a release or cache-key adjustment This type of question is often hard to answer quickly without knowing the exact field names in the dataset. MCP discovers the relevant keys first, then narrows the search — making it easier to see which paths are driving origin load and whether the issue is broad or concentrated. ### Example 5 — Investigate abusive or unusual traffic ``` Use CDN logs from the last 15 minutes to find unusual request-volume spikes by client IP, user agent, host, and path. ``` **What to look for in CDN logs:** * Sudden traffic concentration from a small set of IPs * Repeated hits to a small set of endpoints * Suspicious user-agent patterns * Abnormal request mix compared with baseline traffic This helps identify bot traffic, scraper spikes, attack reconnaissance, or accidental client retry storms. The workflow makes it easier to isolate sudden spikes, see which IPs or paths dominate the burst, and decide quickly whether you are looking at bots, scrapers, or retry storms. *** ## Frequently Asked Questions **Which login methods are supported for MCP?** Hosted MCP supports the same login methods available across the rest of Bronto: OAuth, SSO, and Google Social. Your admin controls which are enabled for MCP access via the Authentication settings page. **Can I restrict which users can connect via MCP?** Yes. Because MCP access is tied to the same login controls as the rest of the product, disabling a login method for MCP prevents users who rely on that method from completing the MCP OAuth flow, giving admins fine-grained control over who can access Bronto via MCP. **Do I need to run anything locally?** No. With the hosted MCP endpoint there is no local server to install or manage. The only exception is if you are using mcp-remote as a bridge for stdio-only clients — but even then, mcp-remote is a lightweight npx invocation rather than a persistent service you need to maintain. **Which header carries the API key?** Pass the API key in the `X-BRONTO-API-KEY` request header. **What is the difference between the US and EU endpoints?** The endpoints correspond to the data region where your Bronto account is hosted. Use `mcp.us.bronto.io` for US accounts and `mcp.eu.bronto.io` for EU accounts. Connecting to the wrong region will result in an authentication error. # LLM Observability Source: https://docs.bronto.io/ai-features/llm-observability Capture, send, and search OpenTelemetry GenAI telemetry in Bronto — prompts, responses, token usage, model metadata, and tool calls from LLM apps. LLM observability in Bronto is built on the [OpenTelemetry GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) — a standard set of `gen_ai.*` attributes for model calls. Any application emitting these attributes on spans or log records gets first-class, searchable prompt/response, token usage, and model fields in Bronto automatically — no Bronto-specific SDK. This documentation was verified on **July 17, 2026** and uses the latest OpenTelemetry GenAI semantic conventions available on that date. GenAI instrumentation evolves rapidly: current library releases may add the latest conventions while retaining legacy output for compatibility, so the schema emitted by default can vary by library and version. ## Convention version and opt-in To avoid breaking existing dashboards and queries, instrumentation libraries are not required to switch their default output when a newer Development convention is released. Where supported, enable the current convention with this OpenTelemetry migration opt-in: ```bash theme={"dark"} export OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental ``` Support for this opt-in is **instrumentation-specific**, not universal. Check the relevant [language instrumentation page](/opentelemetry/overview) and your installed package version before relying on it. Some libraries already emit the current fields by default, some require a different setting, and some still emit an older schema even when this variable is present. ## 1. Instrument your application Pick your language for the generic `gen_ai.*` mechanics — auto-instrumentation where it exists, manual spans where it doesn't, and the experimental content-capture flags: GenAI auto-instrumentation for supported Python model clients. Auto-instrumentation for OpenAI, plus alternatives. Javaagent-based GenAI coverage (also covers Kotlin). .NET, Go, Ruby, PHP, Rust, C++, Swift, Erlang/Elixir. Using a specific framework or cloud GenAI service? These pages cover the OTel setup and the telemetry available from each integration: `Converse` / `InvokeModel` via botocore instrumentation. Agent-loop traces with the Strands framework. Broad provider and framework instrumentation from Traceloop. Chain instrumentation, with optional LangSmith OTel routing. Agent and LLM telemetry from Foundry apps, exported straight to Bronto. ## 2. Send it to Bronto Export through an OTel Collector or directly — see [Connect OpenTelemetry to Bronto](/agent-setup/open-telemetry) or the "Direct export to Bronto" section on any language page. ## 3. Know what you'll see The most useful `gen_ai.*` attributes: | Attribute | What it represents | Good for | | - | - | - | | `gen_ai.provider.name` | Model provider, e.g. `openai`, `aws.bedrock` | Filtering and grouping by provider | | `gen_ai.operation.name` | Operation type, e.g. `chat` | Breaking down traffic by operation | | `gen_ai.request.model` / `gen_ai.response.model` | Requested / actual model served | Comparing usage by model | | `gen_ai.input.messages` / `gen_ai.output.messages` | Prompt / response payload | Inspecting exact input and generated output | | `gen_ai.system_instructions` | System prompt or instruction block | Auditing assistant behavior | | `gen_ai.response.finish_reasons` | Array of finish reasons, e.g. `["stop"]` | Spotting truncation or unusual stops | | `gen_ai.response.time_to_first_chunk` | Seconds from issuing a streaming request until the first response chunk arrives | Measuring perceived streaming latency on individual spans | | `gen_ai.usage.input_tokens` / `gen_ai.usage.output_tokens` | Token counts | Cost and usage analysis | | `gen_ai.usage.cache_read.input_tokens` / `gen_ai.usage.cache_creation.input_tokens` | Provider-managed prompt-cache usage | Understanding cache effectiveness and billed input | | `gen_ai.usage.reasoning.output_tokens` | Reasoning tokens, when reported | Analyzing reasoning-model usage | | `gen_ai.response.id` | Provider response ID | Tracing a specific completion | OpenTelemetry also defines latency metric instruments for aggregate analysis: | Metric | What it measures | When to use it | | - | - | - | | `gen_ai.client.operation.time_to_first_chunk` | Time from issuing a request until the client receives the first response chunk | Client-side histogram for streaming responses only | | `gen_ai.client.operation.duration` | Total time from issuing a request until the operation completes | Streaming and non-streaming responses; this is the time-to-completion measure for non-streaming responses | | `gen_ai.server.time_to_first_token` | Time from receiving a request until the model server generates its first output token | Server-side model instrumentation, when available | Instrumentation does not yet use these boundaries consistently. Traceloop and Strands releases may emit `gen_ai.server.time_to_first_token` from client or framework instrumentation, while Amazon Bedrock publishes a separate CloudWatch `TimeToFirstToken` metric for streaming APIs. Preserve the field emitted by your instrumentation and confirm its unit and measurement boundary before comparing providers. Content capture is instrumentation-specific and can expose sensitive data. Official Python, JavaScript, and Java instrumentations generally default it off; Traceloop and Strands differ. Prefer a supported span-attribute mode such as Python OpenAI v2's `span_only` so `gen_ai.input.messages` / `gen_ai.output.messages` are queryable on traces. Where content is emitted as OTel log events—or no span-attribute mode exists—emit a structured **log record** correlated by `trace_id`: ```python theme={"dark"} logger.info( "chat.completion", extra={ "gen_ai.provider.name": "openai", "gen_ai.operation.name": "chat", "gen_ai.request.model": "gpt-4o-mini", "gen_ai.input.messages": prompt, "gen_ai.output.messages": response_text, "gen_ai.usage.input_tokens": 33, "gen_ai.usage.output_tokens": 74, }, ) ``` Setting attributes manually on a span (no auto-instrumentation for your provider)? Same idea: ```python theme={"dark"} with tracer.start_as_current_span("chat gpt-4o-mini") as span: span.set_attribute("gen_ai.provider.name", "openai") span.set_attribute("gen_ai.operation.name", "chat") span.set_attribute("gen_ai.request.model", "gpt-4o-mini") span.set_attribute("gen_ai.usage.input_tokens", 33) span.set_attribute("gen_ai.usage.output_tokens", 74) span.set_attribute("gen_ai.response.finish_reasons", ["stop"]) ``` ## 4. Search and aggregate Open [Log Search](https://app.bronto.io/search) and use field predicates to select GenAI calls. For example, select Bedrock calls that report input-token usage: ```sql theme={"dark"} "$gen_ai.provider.name" = 'aws.bedrock' AND "$gen_ai.usage.input_tokens" > 0 ``` Build token-usage views with `$gen_ai.provider.name` as the group-by field: | Analysis | Aggregation | Numeric field | Group by | | - | - | - | - | | Total input-token usage | **Sum** | `$gen_ai.usage.input_tokens` | `$gen_ai.provider.name` | | Total output-token usage | **Sum** | `$gen_ai.usage.output_tokens` | `$gen_ai.provider.name` | | Typical tokens per call | **Median** | `$gen_ai.usage.input_tokens` or `$gen_ai.usage.output_tokens` | `$gen_ai.provider.name` | | High-token calls | **P75**, **P90**, **P95**, or **P99** | `$gen_ai.usage.input_tokens` or `$gen_ai.usage.output_tokens` | `$gen_ai.provider.name` | | Prompt-cache activity | **Sum** | `$gen_ai.usage.cache_read.input_tokens` or `$gen_ai.usage.cache_creation.input_tokens` | `$gen_ai.provider.name` | | Reasoning-token usage | **Sum** | `$gen_ai.usage.reasoning.output_tokens` | `$gen_ai.provider.name` | Bronto time-series views also provide **Count**, **Average**, **Min**, **Max**, **Sum**, and **Median**; median is the 50th percentile. Dashboard percentile views provide **P75**, **P90**, **P95**, and **P99**. Use a median to compare typical token consumption and the higher percentiles to find providers or models producing unusually large responses. For streaming latency on spans, apply the same median and percentile views to `$gen_ai.response.time_to_first_chunk`, grouped by `$gen_ai.provider.name`. If your instrumentation exports metrics, chart `gen_ai.client.operation.time_to_first_chunk` for client-observed streaming latency, `gen_ai.client.operation.duration` for total completion time, or `gen_ai.server.time_to_first_token` for model-server TTFT. `gen_ai.response.finish_reasons` remains an OpenTelemetry array attribute. Bronto indexes its first element as `$gen_ai.response.finish_reasons.0`; `.0` is not part of the semantic-convention name and is not normally added by the Collector. See [Visualizations](/Search-and-Visualize/Log-Visualization) for building these views into a dashboard. ## References * [Connect OpenTelemetry to Bronto](/agent-setup/open-telemetry) * [OpenTelemetry GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) * [OpenTelemetry GenAI metric conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-metrics.md) * [Log Search](/Search-and-Visualize/Log-Search) * [Custom Parser](/core-features/custom-parser) # Local MCP Server Source: https://docs.bronto.io/ai-features/local-mcp Run the open-source Bronto MCP server locally with Python and connect Claude Code or any MCP agent to your datasets, API keys, and search tools. The local MCP server is open source and available on [GitHub](https://github.com/brontoio/bronto-mcp-server). If you prefer not to run infrastructure locally, see the [Hosted MCP Server](./hosted-mcp) instead. ## Overview The Bronto MCP server is a local Python server that exposes Bronto's log-dataset and search capabilities to any MCP-compatible AI agent. Dataset search covers logs; metrics and traces are not stored in datasets or collections and are viewed in their dedicated explorers. Once running, it gives agents the tools to answer questions against your live log data, for example: > *"Can you provide some log events from datasets in the ingestion collection, except for the ones related to garbage collection? The data should be between 2025-05-10 16:05:45 and 2025-05-10 16:25:05."* The server has been tested with Claude Code and should work with any agent that supports the MCP protocol. *** ## Prerequisites * Python 3 installed on your machine * A Bronto API key (see [API Keys](../Account-Management/API-Keys)) * Your Bronto API endpoint URL *** ## Installation Check out the project from GitHub: ```bash theme={"dark"} git clone https://github.com/brontoio/bronto-mcp-server.git cd bronto-mcp-server ``` Create a Python virtual environment at the root of the project: ```bash theme={"dark"} python3 -m venv env ``` Install the required packages into the virtual environment: ```bash theme={"dark"} env/bin/pip install -r requirements.txt ``` *** ## Configuration The MCP server is configured using environment variables. Set both before starting the server. | Variable | Description | Example | | - | - | - | | `BRONTO_API_KEY` | A valid Bronto API key | `68ba7ae3-...` | | `BRONTO_API_ENDPOINT` | The Bronto API endpoint for your region | `https://api.eu.bronto.io` | | Region | API Endpoint | | - | - | | US | `https://api.us.bronto.io` | | EU | `https://api.eu.bronto.io` | *** ## Starting the Server Run the following command from the root of the project, substituting your API key and endpoint: ```bash theme={"dark"} BRONTO_API_KEY= \ BRONTO_API_ENDPOINT=https://api.eu.bronto.io \ PYTHONPATH=src/main/ \ env/bin/python src/main/brmcpserver/main.py ``` The server starts on `http://localhost:8000` by default. Keep your terminal session open while using the MCP server. Closing it will stop the server and disconnect any connected agents. *** ## Connecting Claude Code Once the server is running, register it with Claude Code using the following command: ```bash theme={"dark"} claude mcp add --transport http bronto http://localhost:8000 ``` This makes the Bronto MCP server available for your current project folder. To make it available globally across all projects, add the `--scope user` flag: ```bash theme={"dark"} claude mcp add --transport http bronto http://localhost:8000 --scope user ``` Full documentation on managing MCP servers in Claude Code is available at [docs.anthropic.com](https://docs.anthropic.com/en/docs/claude-code/mcp). ### Verify the connection Launch Claude Code and run the `/mcp` command to confirm the Bronto MCP server is available and connected: ``` /mcp ────────────────────────────────────── Manage MCP servers 1 servers Local MCPs ❯ bronto · ✓ connected ``` *** ## Capabilities Once connected, the server exposes the following tools to your AI agent. | Tool | Description | When to use | | - | - | - | | `get_datasets` | Fetches all datasets in your Bronto account, including name, collection, dataset ID, and tags. Tags such as `description`, `service`, `team`, and `environment` are especially useful for understanding dataset contents. | When you need to discover what data sources are available, or find datasets by owner or environment. | | `get_datasets_by_name` | Fetches a specific dataset by its exact name and collection name. A dataset is uniquely identified by the combination of both. | When you already know the dataset and collection name and need its log ID or tag metadata. | | `get_keys` | Returns all field names present in a specific dataset, identified by its log ID. | To inspect a single dataset's schema before querying or filtering it. | | `get_all_datasets_keys` | Returns a map of dataset IDs to their field names across all datasets. | To identify which datasets contain a particular field, or to determine the exact field name from a description. | | `get_key_values` | Returns the available values for a specific field in a specific dataset. | To discover valid field values and build precise filters before running a search. | | `search_logs` | Searches raw events across one or more datasets over a time range. Supports SQL-style `WHERE` filters, multiple dataset IDs, and returns full events including the `@raw` field. | Event-level investigations where you need to inspect individual entries — for example, finding errors or warnings in a specific service. | *** ## Frequently Asked Questions **Which AI agents are supported?** The server implements the MCP protocol and should work with any MCP-compatible agent. It has been tested with Claude Code. **Can I make the server available across all my projects?** Yes. Add `--scope user` when registering the server with Claude Code and it will be available globally rather than only for the current project folder. **Where do I find my API key?** API keys can be created and managed in **Settings → API Keys** in the Bronto UI. See [API Keys](../Account-Management/API-Keys) for details. **What is the difference between the local server and the hosted MCP server?** The local server runs on your machine and requires Python, a virtual environment, and a running terminal session. The [hosted MCP server](./hosted-mcp) is managed by Bronto — there is nothing to install or run locally. For most teams the hosted option is simpler; the local server is useful if you need to run in an air-gapped environment or want to inspect or modify the server code directly. # Microsoft Foundry observability with OpenTelemetry Source: https://docs.bronto.io/ai-features/microsoft-foundry Send logs, metrics, and traces from Microsoft Foundry apps and agents to Bronto over OTLP — gen_ai spans, token usage, tool calls, and multi-agent traces. Apps and agents built on [Microsoft Foundry](https://learn.microsoft.com/en-us/azure/foundry/) (formerly Azure AI Foundry) are already OpenTelemetry-instrumented: the supported SDKs and agent frameworks emit spans following the [OpenTelemetry GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) — model calls, token usage, tool invocations, and multi-agent task hierarchies. Because that telemetry is standard OpenTelemetry, one initialisation block sends **logs, metrics, and traces** from your Foundry app straight to Bronto over OTLP/HTTP — no Bronto-specific SDK involved. This page covers the app-level signal. For general Azure platform, diagnostic, and activity logs from the same subscription, see [Ingesting Azure Data into Bronto](/integrations/azure-overview); for the attributes Bronto surfaces and how to search them, see [LLM Observability](/ai-features/llm-observability). GenAI instrumentation moves quickly. The package names, environment variables, and default attribute shapes below reflect the instrumentation available at the time of writing — confirm them against the release you deploy, and inspect a real trace before building version-sensitive dashboards. ## Prerequisites * A Microsoft Foundry project with an instrumented app or agent * Python 3.10 or later, and `pip` * A Bronto ingestion API key — see [API Keys](/Account-Management/API-Keys#create-a-new-api-key) for how to create one with ingestion permissions * Your Bronto region: `eu` or `us` * A service name and namespace for the app's telemetry. These resource attributes identify all three signals; for logs only, `service.name` selects the dataset and `service.namespace` selects the collection. Metrics and traces do not appear in datasets or collections. ## Choose an OpenTelemetry-native instrumentation Every framework in the Foundry ecosystem has more than one way to produce GenAI telemetry: vendor distributions such as [OpenLLMetry](/integrations/openllmetry) or OpenInference wrap the framework in their own SDK, while the OpenTelemetry-native route uses either upstream OpenTelemetry instrumentation or the telemetry the framework emits itself. This page assumes the OpenTelemetry-native route. It keeps `gen_ai.*` attributes aligned with the upstream semantic conventions, puts no vendor SDK in the request path, and means the exporter configuration below is the only Bronto-specific code you write. | Framework | OpenTelemetry-native route | Documentation | | - | - | - | | OpenAI SDK / Azure OpenAI | `opentelemetry-instrumentation-openai-v2`, an upstream OpenTelemetry contrib package | [opentelemetry-python-contrib](https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation-genai/opentelemetry-instrumentation-openai-v2) | | Semantic Kernel | Emits OpenTelemetry traces, metrics, and logs itself — no instrumentation package, but its GenAI diagnostics are behind an experimental switch | [Observability in Semantic Kernel](https://learn.microsoft.com/en-us/semantic-kernel/concepts/enterprise-readiness/observability/) | | Microsoft Agent Framework | Emits OpenTelemetry telemetry itself, enabled through the framework's own observability setup | [Agent Framework observability](https://learn.microsoft.com/en-us/agent-framework/user-guide/observability/) | | OpenAI Agents SDK | Its own tracing layer with pluggable processors; bridge it to OpenTelemetry with an OTel trace processor | [OpenAI Agents SDK tracing](https://openai.github.io/openai-agents-python/tracing/) | | LangChain / LangGraph | OTLP export, either via an OpenTelemetry instrumentation package or LangSmith's OTLP endpoint routing | [LangChain](/integrations/langchain), [LangSmith OpenTelemetry](https://docs.smith.langchain.com/observability/how_to_guides/opentelemetry) | | Foundry Agent Service (`azure-ai-agents`) | An instrumentor shipped with the Azure SDK, covering agent runs and tool calls | [Observability in generative AI](https://learn.microsoft.com/en-us/azure/foundry/concepts/observability) | Whichever you choose, everything below is identical — the exporter, the endpoints, the credential, the resource attributes — because all of these emit through the OpenTelemetry providers you configure. Verify the exact package name, import path, and enablement call for your framework against its own documentation before copying this table into a runbook. Only the OpenAI SDK row is exercised by the code samples below. ## Install the SDK and instrumentation ```bash theme={"dark"} pip install \ opentelemetry-sdk \ opentelemetry-exporter-otlp-proto-http \ opentelemetry-instrumentation-openai-v2 ``` Swap the last package for the instrumentation your framework uses, or drop it entirely for a framework that emits OpenTelemetry itself. ## Endpoints and authentication Bronto has one OTLP/HTTP endpoint per signal, per region. Every request carries the API key in the `x-bronto-api-key` header. | Signal | EU region | US region | | - | - | - | | Logs | `https://ingestion.eu.bronto.io/v1/logs` | `https://ingestion.us.bronto.io/v1/logs` | | Metrics | `https://ingestion.eu.bronto.io/v1/metrics` | `https://ingestion.us.bronto.io/v1/metrics` | | Traces | `https://ingestion.eu.bronto.io/v1/traces` | `https://ingestion.us.bronto.io/v1/traces` | The SDK appends `/v1/logs`, `/v1/metrics`, and `/v1/traces` to `OTEL_EXPORTER_OTLP_ENDPOINT` automatically, so configure the **base** URL and let one setting cover all three signals: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingestion..bronto.io" # eu or us export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf" export OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=" export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE="delta" # Shared signal identity; these select the dataset and collection for logs only. export OTEL_SERVICE_NAME="foundry-agent" export OTEL_RESOURCE_ATTRIBUTES="service.namespace=ai-apps,deployment.environment=production" ``` ## Configure logs, metrics, and traces Add this module to your project and call `configure_bronto_telemetry()` once, at the very top of your entrypoint — before the instrumented client is constructed and before your first log statement or span. ```python otel_bronto.py theme={"dark"} import logging from opentelemetry import metrics, trace from opentelemetry._logs import set_logger_provider from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler from opentelemetry.sdk._logs.export import BatchLogRecordProcessor from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor def configure_bronto_telemetry() -> tuple[TracerProvider, MeterProvider, LoggerProvider]: # Reads OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES — one identity for # all three signals, which is what makes them correlate in Bronto. resource = Resource.create() # Traces — GenAI spans from your instrumentation land here. tracer_provider = TracerProvider(resource=resource) tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter())) trace.set_tracer_provider(tracer_provider) # Metrics — GenAI metric instruments plus anything your app records. reader = PeriodicExportingMetricReader(OTLPMetricExporter()) meter_provider = MeterProvider(resource=resource, metric_readers=[reader]) metrics.set_meter_provider(meter_provider) # Logs — bridges the standard logging module, so structured `extra=` fields # arrive as queryable attributes and existing log statements are unchanged. logger_provider = LoggerProvider(resource=resource) logger_provider.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter())) set_logger_provider(logger_provider) logging.getLogger().addHandler(LoggingHandler(logger_provider=logger_provider)) logging.getLogger().setLevel(logging.INFO) return tracer_provider, meter_provider, logger_provider ``` The exporters take no arguments because they read the endpoint, protocol, and headers from the environment. To keep configuration in code instead, pass the **full** signal path to each one — `OTLPSpanExporter(endpoint="https://ingestion..bronto.io/v1/traces", headers={"x-bronto-api-key": ...})`, and likewise for logs and metrics. Enable instrumentation after the providers are registered, and build your client after that: ```python app.py theme={"dark"} import os from otel_bronto import configure_bronto_telemetry tracer_provider, meter_provider, logger_provider = configure_bronto_telemetry() # Instrumentation attaches to the registered providers. from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor OpenAIInstrumentor().instrument() from openai import AzureOpenAI client = AzureOpenAI( azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"], api_key=os.environ["AZURE_OPENAI_API_KEY"], api_version="", ) response = client.chat.completions.create( model="", messages=[{"role": "user", "content": "Summarise today's incidents."}], ) ``` Any log emitted inside an active span automatically carries that span's `trace_id` and `span_id`, so you can jump from a log line to the model call that produced it with no manual context propagation. **Short-lived processes.** The batch processors and the metric reader export on a timer, so a script, job, or evaluation run that exits immediately can drop its last batch. Shut the providers down before exit: ```python theme={"dark"} tracer_provider.shutdown() meter_provider.shutdown() logger_provider.shutdown() ``` **Framework spans without code changes.** Install the `opentelemetry-instrumentation-` packages for your web framework and HTTP client and run your app with `opentelemetry-instrument python app.py`. The CLI configures the providers itself from the same `OTEL_*` variables above, so use it *instead of* `otel_bronto.py` — and add `opentelemetry-instrumentation-logging` so standard-library logs are still bridged. See [Python zero-code instrumentation](https://opentelemetry.io/docs/zero-code/python/). ## Capturing prompts and responses Two environment variables control whether the text of prompts and completions is captured, and in what shape: ```bash theme={"dark"} export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=span_only export OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental ``` * `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` turns content capture on. It is **off by default** in the official instrumentations. `span_only` writes content to `gen_ai.input.messages` and `gen_ai.output.messages` as span attributes, which Bronto surfaces as searchable trace fields. The legacy `true` setting emits content as separate log records correlated by `trace_id`, where it is not queryable on the span itself — prefer `span_only` where your instrumentation supports it. Either way the content reaches Bronto, because the setup above exports logs as well as traces. * `OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental` opts into the current GenAI convention shape. Instrumentation libraries keep emitting an older schema by default so they don't break existing dashboards, and support for this opt-in is **instrumentation-specific** — some libraries already emit the current fields, some need a different setting, some ignore it entirely. Exercise caution when capturing prompts and responses — depending on the nature of your application they may include sensitive data. Semantic Kernel and Microsoft Agent Framework do not use `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` — each has its own switch for sensitive-data capture. See their observability documentation, linked in the table above, for the exact variable names. ## What you'll see in Bronto ### Traces One app or agent invocation becomes one trace with nested spans: | Span | Source | Notes | | - | - | - | | Request / invocation | Your app or web framework instrumentation | Root span for the request | | Agent or task span | Agent framework | One per agent step; multi-agent runs nest handoffs beneath the orchestrator | | `chat` | GenAI instrumentation | One per model call, carrying `gen_ai.*` attributes | | Tool call | Agent framework | One child span per tool the agent invokes | The attributes worth knowing on the model spans: | Attribute | Example | Notes | | - | - | - | | `gen_ai.provider.name` | `openai` | Provider — filter and group by this | | `gen_ai.operation.name` | `chat` | Operation type | | `gen_ai.request.model` / `gen_ai.response.model` | `gpt-4o-mini` | Requested model / model actually served | | `gen_ai.usage.input_tokens` / `gen_ai.usage.output_tokens` | `412`, `173` | Numeric — sum, average, and chart these | | `gen_ai.response.finish_reasons.0` | `stop` | Bronto indexes the first element of the array attribute | | `gen_ai.tool.name` / `gen_ai.tool.call.id` | `get_weather` | On tool-call spans, where the framework emits them | | `gen_ai.input.messages` / `gen_ai.output.messages` | — | Only present when content capture is enabled | Open [Explore Traces](/tracing/explore-traces) and filter by the `service.name` you set. Open the newest trace and confirm the nesting above: the invocation at the root, a `chat` span per model call, and tool-call spans beneath it. ### Metrics Where your instrumentation implements the [GenAI metric conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-metrics.md), the meter provider exports aggregate instruments alongside the spans: | Metric | What it measures | | - | - | | `gen_ai.client.operation.duration` | Total time from issuing a request until the operation completes | | `gen_ai.client.token.usage` | Token usage per call, as a histogram | | `gen_ai.client.operation.time_to_first_chunk` | Client-observed streaming latency | | `gen_ai.server.time_to_first_token` | Model-server time to first token, where the server reports it | Open **Metric Explorer** and select a recently emitted metric to confirm it carries the same `service.name`. Coverage of these instruments varies by library and version — spans are the reliable source of token counts, metrics the cheaper source of aggregate latency. See [Explore Metrics](/metrics/explore-metrics) for building views. ### Logs Application logs from the bridged `logging` module arrive with `trace_id` and `span_id` attached, so they line up with the trace that produced them. Log structured GenAI fields with `extra=` and they become queryable attributes: ```python theme={"dark"} import logging log = logging.getLogger(__name__) log.info( "agent.result", extra={ "event.name": "agent.result", "gen_ai.request.model": "", "session.id": session_id, }, ) ``` Avoid printf-style logging (`log.info("tokens=%s", n)`) for data you want to query — that produces a flat message string rather than structured fields. ### Search and aggregate Bronto indexes attributes with a `$` prefix, so query them in [Log Search](https://app.bronto.io/search) as field predicates: ```sql theme={"dark"} "$gen_ai.provider.name" = 'openai' AND "$gen_ai.usage.input_tokens" > 0 ``` ```sql theme={"dark"} "$gen_ai.output.messages" ILIKE '%rate limit%' ``` Token usage is numeric, so it aggregates: **Sum** of `$gen_ai.usage.output_tokens` grouped by `$gen_ai.request.model` gives per-model consumption; the **P95** of the same field finds unusually large responses. See [LLM Observability](/ai-features/llm-observability) for the full set of aggregations and [Visualizations](/Search-and-Visualize/Log-Visualization) for building them into a dashboard. ## Troubleshooting | Symptom | Likely cause | | - | - | | `401` / `403` from the exporter | Header name must be exactly `x-bronto-api-key`, and the key needs ingestion permissions. In `OTEL_EXPORTER_OTLP_HEADERS`, use `key=value` with no quotes or spaces around the `=`. | | `404` from the exporter | Path mismatch. `OTEL_EXPORTER_OTLP_ENDPOINT` takes the **base** URL and the SDK appends `/v1/logs`, `/v1/metrics`, `/v1/traces`; an explicit `endpoint=` argument takes the **full** signal path. | | Connection or protocol errors | Use the `opentelemetry-exporter-otlp-proto-http` exporters with `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf`. Bronto's ingestion endpoints are OTLP/HTTP on port `443`; the gRPC exporter will not reach them. | | Exports succeed but nothing appears | Wrong region — an EU key against `ingestion.us.bronto.io` (or the reverse) will not land in your account. Check the region of the endpoint against the region of the key. | | Traces arrive, metrics don't | Exponential histograms are rejected. Leave the default explicit-bucket aggregation, and set `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta`. See [Send Metrics to Bronto](/metrics/send-metrics). | | No spans at all | Instrumentation was enabled before the providers were registered, the instrumented client was constructed before either, or the instrumentation package isn't installed. Register the providers first, instrument second, build clients third. | | Signals appear in long runs but not in jobs | The process exits before the batch processors flush. Call `shutdown()` on each provider before exit. | | Spans arrive, prompts and responses are empty | Content capture is off by default. See [Capturing prompts and responses](#capturing-prompts-and-responses) — and confirm your framework honours that variable. | | Attribute names don't match this page | Your instrumentation is emitting an older convention. Try `OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental`, and inspect a real trace to see what the installed version actually emits. | ## Node.js and TypeScript The pattern is the same: build the three providers with the OTLP/HTTP exporters from `@opentelemetry/exporter-trace-otlp-proto`, `@opentelemetry/exporter-metrics-otlp-proto`, and `@opentelemetry/exporter-logs-otlp-proto`, pointed at the same base endpoint with the same `x-bronto-api-key` header, then register your framework's instrumentation. See [Send Node.js logs, metrics, and traces to Bronto](/opentelemetry/nodejs) for the full setup. ## References * [LLM Observability](/ai-features/llm-observability) * [OpenTelemetry on Azure](/integrations/azure-otel) * [Send Python logs, metrics, and traces to Bronto](/opentelemetry/python) * [Send Metrics to Bronto](/metrics/send-metrics) * [Microsoft Foundry documentation](https://learn.microsoft.com/en-us/azure/foundry/) * [Observability in generative AI](https://learn.microsoft.com/en-us/azure/foundry/concepts/observability) * [OpenTelemetry GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) * [OpenTelemetry GenAI metric conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-metrics.md) *** For assistance or questions, contact [support@bronto.io](mailto:support@bronto.io). # n8n Integration Source: https://docs.bronto.io/ai-features/n8n Connect Bronto to n8n workflows to query logs, trigger automations on observability data, and build AI-assisted incident response pipelines. [n8n](https://n8n.io) is an open-source workflow automation platform that lets you connect APIs, services, and AI agents without writing glue code. The Bronto n8n node gives workflows direct access to your log data — so you can query, filter, aggregate, and act on observability data from inside any n8n pipeline. Together, Bronto and n8n let you close the loop between your observability data and the rest of your stack: pull log context into incident tickets, route anomaly data to AI agents, enrich alerts with search results, or schedule regular health-check queries without maintaining custom scripts. ## Use cases ### Incident response automation Trigger an n8n workflow from a Bronto monitor alert webhook. The workflow queries Bronto for recent errors or anomalies around the alert window, formats a summary, and creates a ticket in Linear, Jira, or PagerDuty — with log context already attached. ### AI-assisted log investigation Use the Bronto node as an [AI tool node](https://docs.n8n.io/advanced-ai/examples/understand-tools/) inside an n8n AI agent workflow. The agent calls Bronto search at runtime to look up relevant logs, then synthesizes findings and posts a summary to Slack or email. ### Scheduled health checks Run a recurring n8n workflow that queries Bronto for error rates, latency distributions, or specific log patterns on a schedule. Compare results against thresholds and notify your team when something drifts. ### Log-driven data pipelines Extract structured fields from Bronto log events and push them to a data warehouse, spreadsheet, or analytics tool. Useful for compliance exports, capacity planning, or building custom dashboards outside of Bronto. ### Cross-tool correlation Combine Bronto log data with data from other systems in the same workflow — query deployment events from GitHub, pull error counts from Bronto, and correlate them to detect regressions after releases. ## Minimal install The Bronto node is a verified community node hosted on npm and the n8n community node registry. **Requirements** * n8n v0.187.0 or later (self-hosted or n8n Cloud) * Instance owner access to install community nodes **Install from the n8n UI** 1. Open **Settings → Community nodes** 2. Click **Install a community node** 3. Enter the package name: `n8n-nodes-bronto` 4. Confirm and restart n8n if prompted **Install manually (self-hosted)** ```bash theme={"dark"} cd /usr/local/lib/node_modules/n8n # adjust to your n8n install path npm install n8n-nodes-bronto ``` Source code and issue tracker: [github.com/brontoio/n8n-nodes-bronto](https://github.com/brontoio/n8n-nodes-bronto) ## Credential setup After installing the node, create a **Bronto API** credential in n8n: 1. Go to **Credentials → Add credential → Bronto API** 2. Enter your Bronto API key — create one under **Account Management → API Keys** with search permissions 3. Select your region: **EU** or **US** The region determines the base URL the node uses (`https://api.eu.bronto.io` or `https://api.us.bronto.io`). ## Node reference The Bronto node has a single **Search** operation that queries the Bronto search API. ### Source Choose how to identify which logs to search: | Source type | Description | | - | - | | **Logs** | Select one or more log datasets from a dropdown populated from your Bronto account | | **Tags** | Filter by tag key:value pairs (e.g. `env:production service:api`) | ### Search parameters | Parameter | Description | Example | | - | - | - | | **Time range** | Relative time window | `Last 1 hour`, `Last 2 days` | | **Where** | SQL-like filter expression | `level:error AND duration_ms>2000` | | **Select** | Fields or aggregate functions to return | `*, @raw` or `count(), avg(duration_ms)` | | **Groups** | Fields to group aggregate results by | `service, region` | | **Limit** | Maximum number of results (1–6666) | `50` | ### Additional options | Option | Description | | - | - | | **From / To timestamp** | Absolute time bounds in Unix milliseconds | | **Most recent first** | Sort order — newest events first (default: true) | | **Number of slices** | Time buckets for time-series aggregate queries | | **Paginate** | Automatically follow `next_page_url` to fetch all matching results | ### Output The node maps the API response to n8n items in one of three shapes depending on the query: * `events[]` — individual log events from a raw search * `groups[]` — grouped rows from an aggregate query * `result[]` — other result arrays Each item is available to downstream nodes as a standard n8n JSON object. ## Use as an AI tool node The Bronto node supports n8n's `usableAsTool` flag, meaning it can be connected directly to an AI agent node without wrapping. When used this way, the agent decides at runtime when and how to call the Bronto search — passing a query, time range, and filter based on context from the conversation or workflow. This is the recommended pattern for AI-assisted log investigation workflows where the query is not known in advance. # OpenClaw Integration Source: https://docs.bronto.io/ai-features/openclaw Instrument OpenClaw agents with OpenTelemetry to send AI agent logs, metrics, and traces to Bronto for observability, debugging, and cost tracking. ## Overview [OpenClaw](https://openclaw.ai) is a self-hosted personal AI assistant. Its gateway includes a built-in [`diagnostics-otel`](https://docs.openclaw.ai/gateway/opentelemetry) plugin that exports OpenTelemetry logs, metrics, and traces over OTLP/HTTP. Pointed at Bronto, every model call your assistant makes lands in Bronto with full token, model, provider, and (optionally) prompt/response context. You can ship telemetry to Bronto in one of two ways: 1. **Through an OpenTelemetry Collector that forwards to Bronto** *(recommended)*. More reliable and easier to debug when something doesn't show up in Bronto. 2. **Directly from the `diagnostics-otel` plugin to Bronto's OTLP endpoints**. Fewer moving parts, but harder to troubleshoot. This page applies wherever you run the OpenClaw gateway — Docker, a VM, or a managed host — and does not assume any particular cloud. If you've tried the direct route and don't see data in Bronto, use the OpenTelemetry Collector path. * The Collector batches and retries on OpenClaw's behalf * Its `debug` exporter prints every signal it receives. This is a reliable way to tell whether a missing signal is OpenClaw failing to emit it or Bronto-side configuration (API key, region, headers) being wrong. * The Collector logs failures with full details so network-level problems surface immediately. ## Before you start You will need: * A running OpenClaw gateway. The configuration is the same wherever the gateway runs - only the path to `openclaw.json` and `~/.openclaw/.env` differs. * A Bronto API key — see [API Keys](/Account-Management/API-Keys). * Your Bronto region (`eu` or `us`) — see [Bronto Ingestion Endpoints](/getting-started/bronto-endpoints). The `diagnostics-otel` plugin must be installed and enabled on the gateway: ```bash theme={"dark"} openclaw plugins install clawhub:@openclaw/diagnostics-otel openclaw plugins enable diagnostics-otel ``` ## Recommended: OpenTelemetry Collector ### 1. Run a Collector next to OpenClaw Install the OpenTelemetry Collector on the same host as the OpenClaw gateway, or anywhere the gateway can reach over the network. The [OpenTelemetry Collector installation docs](https://opentelemetry.io/docs/collector/installation/) cover Docker, Linux packages, Homebrew, Windows, and Kubernetes; see also [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) for richer Bronto-specific configuration. Use the config below as your starting point. * It accepts OTLP/HTTP on port `4318` * It prints every received signal to the Collector's standard output via the `debug` exporter * It forwards everything to Bronto. The `debug` exporter is included intentionally, as it is a useful tool for confirming that signals are reaching the Collector, and what they look like. **Recommended for initial setup**, but remove it from the `exporters` block and from each pipeline once telemetry is flowing reliably into Bronto. ```yaml otel-collector-config.yaml theme={"dark"} receivers: otlp: protocols: http: endpoint: "0.0.0.0:4318" processors: batch: exporters: debug: verbosity: detailed otlphttp/brontotraces: traces_endpoint: "https://ingestion..bronto.io/v1/traces" compression: gzip headers: x-bronto-api-key: otlphttp/brontometrics: metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" compression: gzip headers: x-bronto-api-key: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: x-bronto-dataset: openclaw x-bronto-collection: openclaw-demo service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [debug, otlphttp/brontotraces] metrics: receivers: [otlp] processors: [batch] exporters: [debug, otlphttp/brontometrics] logs: receivers: [otlp] processors: [batch] exporters: [debug, otlphttp/brontologs] ``` Replace `` with `eu` or `us` and `` with your Bronto API key. Per-signal endpoints (`traces_endpoint`, `logs_endpoint`, `metrics_endpoint`) are required because Bronto's OTLP host does not follow the default OTLP path convention. The dataset and collection headers are intentionally present only on the logs exporter. OpenClaw logs appear in the `openclaw-demo/openclaw` dataset, metrics appear in the Metric Explorer, and traces appear in Explore Traces. Metrics and traces do not create datasets or collections. ### 2. Point OpenClaw at the Collector Add a `diagnostics` block at the **top level** of your `~/.openclaw/openclaw.json`, alongside the existing top-level keys (`gateway`, `agents`, `models`, `plugins`, etc..., not nested inside any of them). ```json openclaw.json theme={"dark"} { // ...other top-level keys: "gateway", "agents", "models", "plugins", etc. "diagnostics": { "enabled": true, "otel": { "enabled": true, "endpoint": "http://localhost:4318", "protocol": "http/protobuf", "serviceName": "openclaw-gateway", "captureContent": true, "traces": true, "logs": true, "metrics": true, "sampleRate": 1, "flushIntervalMs": 10000 } } // ... } ``` Set `endpoint` to wherever the Collector's OTLP/HTTP receiver is reachable from the gateway. `http://localhost:4318` is correct when both run on the same host. If they run as separate containers on a shared Docker network, use the Collector's service or container name instead (e.g. `http://otel-collector:4318`). Add the following to your `~/.openclaw/.env`: ```bash ~/.openclaw/.env theme={"dark"} OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta ``` `OTEL_SEMCONV_STABILITY_OPT_IN` opts the gateway in to the stable GenAI semantic-convention attributes (`gen_ai.request.model`, `gen_ai.usage.input_tokens`, etc.). It is an environment variable and cannot be set in `openclaw.json`. Without it, spans carry only OpenClaw's own `openclaw.*` attributes. Restart the gateway to pick up the new configuration. Use whichever of the following matches your setup: ```bash theme={"dark"} openclaw gateway restart ``` ```bash theme={"dark"} docker compose restart openclaw-gateway ``` ```bash theme={"dark"} docker restart ``` ```bash theme={"dark"} # systemd systemctl restart openclaw # launchd (macOS) launchctl kickstart -k "gui/$(id -u)/openclaw" # pm2 pm2 restart openclaw ``` ### 3. Confirm signals are flowing Send your OpenClaw assistant a message, then watch the Collector's output. The `debug` exporter writes to the Collector's standard output, so where you find that depends on how you launched it: * **Docker** — `docker logs -f `. * **Foreground terminal** — if you launched the Collector binary directly in a shell, debug lines appear in that terminal. * **systemd** — `journalctl -u otelcol -f` (or `otelcol-contrib -f` for the contrib build). * **Other supervisors** — wherever you redirected the Collector's stdout / stderr (for example `/var/log/otelcol/otelcol.log`). In the output, every signal type appears with its own line prefix: | Prefix | Signal | | - | - | | `Span #` | Trace span | | `LogRecord #` | Log record | | `Metric #` | Metric | If you see all three after sending a message to the assistant, OpenClaw is emitting telemetry correctly. The next thing to verify is that it has reached Bronto: * **Traces** — open [Traces](/tracing/explore-traces) and check that traces for the openclaw-gateway service are visible. * **Logs** — open [Log Search](/Search-and-Visualize/Log-Search) and check for data in the `openclaw-demo/openclaw` dataset. If signals appear in the Collector output but not in Bronto. If they do not appear in the Collector output at all, the failure is upstream of the Collector (plugin not enabled, gateway not restarted, no model activity). See [Troubleshooting](#troubleshooting) ## Alternative: export directly from OpenClaw to Bronto If you cannot run a Collector alongside the gateway, the `diagnostics-otel` plugin can send to Bronto's OTLP endpoints directly. This works, but it gives limited visibility so debugging is harder. ### 1. Configure `openclaw.json` Add a `diagnostics` block at the **top level** of your `~/.openclaw/openclaw.json`. Authenticate with the `x-bronto-api-key` header. ```json openclaw.json theme={"dark"} { // ...other top-level keys: "gateway", "agents", "models", "plugins", etc. "diagnostics": { "enabled": true, "otel": { "enabled": true, "endpoint": "https://ingestion.eu.bronto.io", "tracesEndpoint": "https://ingestion.eu.bronto.io/v1/traces", "logsEndpoint": "https://ingestion.eu.bronto.io/v1/logs", "metricsEndpoint": "https://ingestion.eu.bronto.io/v1/metrics", "protocol": "http/protobuf", "serviceName": "openclaw-gateway", "headers": { "x-bronto-api-key": "${BRONTO_API_KEY}", "x-bronto-dataset": "openclaw", "x-bronto-collection": "openclaw-demo" }, "captureContent": true, "traces": true, "logs": true, "metrics": true, "sampleRate": 1, "flushIntervalMs": 10000 } } } ``` Replace `eu` with `us` if your account is in the US region. The `${BRONTO_API_KEY}` interpolation keeps the secret out of committed config — OpenClaw resolves the variable at load time and fails fast if it is unset. The plugin applies its `headers` object to every signal. Bronto uses `x-bronto-dataset` and `x-bronto-collection` only for the logs request; the same headers do not route metrics or traces into that dataset or collection. OpenClaw's `logs` toggle defaults to `false`, so set `"logs": true` to send log records alongside traces. ### 2. Configure `~/.openclaw/.env` ```bash ~/.openclaw/.env theme={"dark"} BRONTO_API_KEY=YOUR_API_KEY OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta ``` | Variable | Purpose | | - | - | | `BRONTO_API_KEY` | Resolved into the `x-bronto-api-key` header at gateway load. | | `OTEL_SEMCONV_STABILITY_OPT_IN` | Opts in to stable GenAI semantic-convention attributes (`gen_ai.*`). Required for most LLM-observability tooling. Cannot be set in `openclaw.json`. | | `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` | Required by Bronto. | ### 3. Restart and verify Restart the gateway, then send the assistant a message and check Bronto: * **Traces** — open [Traces](/tracing/explore-traces) and check that traces for the openclaw-gateway service are visible. * **Metrics** — open the [Metric Explorer](/metrics/explore-metrics) and filter for the openclaw-gateway service. * **Logs** — open [Log Search](/Search-and-Visualize/Log-Search) and check for data in the `openclaw-demo/openclaw` dataset. The gateway logs only emit a `logs exporter enabled` line on startup — they do **not** log a traces exporter line, and they do **not** log export failures. ## Reference ### Endpoints by region | Region | Traces | Logs | | - | - | - | | EU | `https://ingestion.eu.bronto.io/v1/traces` | `https://ingestion.eu.bronto.io/v1/logs` | | US | `https://ingestion.us.bronto.io/v1/traces` | `https://ingestion.us.bronto.io/v1/logs` | ### Headers | Header | Scope | Description | | - | - | - | | `x-bronto-api-key` | All signals | Bronto ingestion API key (required). | | `x-bronto-dataset` | Logs only | Log dataset name. | | `x-bronto-collection` | Logs only | Collection containing the log dataset — e.g. `production`. | ### Notable `openclaw.json` diagnostics fields | Key | Notes | | - | - | | `protocol` | Must be `http/protobuf`. OpenClaw ignores gRPC. | | `serviceName` | Identifies the source in Bronto — appears as `service.name`. | | `traces` / `logs` | Both default to enabled-with-export, but `logs` requires explicit `true` in some plugin versions. | | `captureContent` | Set `true` to attach prompt and response content to spans. Off by default. | | `sampleRate` | Root-span sampling ratio, `0.0`–`1.0`. Use `1` to capture every model call. | | `flushIntervalMs` | How often the exporter flushes batched signals. | ## Troubleshooting ### Step one: isolate where the failure is Before checking individual settings, determine which side of the pipeline is failing. The Collector path makes this trivial — its `debug` exporter prints every signal it receives. * **If using the Opentelemetry Collector:** Tail the Collector's output (see [Confirm signals are flowing](#3-confirm-signals-are-flowing)) and send the assistant a message. * Signals **appear** in the Collector output but **not** in Bronto → the failure is between the Collector and Bronto. Check the API key, region, and headers in `otel-collector-config.yaml`. * Signals **do not appear** in the Collector output → the failure is upstream of the Collector. The plugin is not enabled, the gateway has not been restarted, or no model activity is being generated. * **If sending telemetry directly:** Test network and auth as described in the next section. If that fails switch to the OpenTelemetry Collector and run the same check. This is by far the fastest way to narrow the failure down - without it, you cannot see what OpenClaw is (or isn't) emitting. ### Network and auth test Use this to check for networking or auth failures between the Collector and Bronto. Run both checks from the same host as the Collector (or your OpenClaw agent, if sending telemetry directly). The examples target the EU region — swap `eu` for `us` if your account is in the US region. **1. DNS resolution.** Empty output means DNS is broken locally (split-DNS on a corporate VPN, misconfigured `resolv.conf` inside a container, captive portal, etc.). ```bash theme={"dark"} dig +short ingestion.eu.bronto.io ``` **2. End-to-end POST.** In the Bronto UI, go to **My Data** (sidebar) → **Add Data** → **Test Connection** (bottom of the page). Bronto generates a `curl` command pre-filled with a hello-world payload and your API key — copy-paste it into a shell on the Collector's host. A `200` proves both connectivity and that the API key is valid for this region. If it fails, re-run with `-vvv` for the full request, TLS handshake, and response, and Google the specific error. ### Common issues **API key incorrect.** Especially common when an AI agent edited the config - agents frequently mis-substitute the key (dropped characters, wrapped in extra quotes, replaced with a placeholder like ``). Re-paste the key by hand and confirm it matches exactly. **Logs arrive in Bronto but no traces or metrics.** This is a known intermittent issue with the `diagnostics-otel` plugin. Fully restart the gateway service — `docker compose restart openclaw-gateway`, or restart the OpenClaw container / supervised process for native installs. A simple reload is not enough. **Traces arrive but no logs.** OpenClaw's `logs` toggle defaults to `false` in some plugin versions. Set `"logs": true` explicitly in `openclaw.json`. **Wrong region.** The API key is region-scoped. EU keys do not work against `us` endpoints and vice versa. Confirm the key's region in Bronto and use the matching `ingestion..bronto.io` host. **Spans arrive but `gen_ai.*` attributes are missing.** Set `OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental` in `~/.openclaw/.env` and restart the gateway. Without it, OpenClaw emits only its own `openclaw.*` attributes. **No prompt/response content on spans.** Expected unless `captureContent` is `true` in the `diagnostics.otel` block. **Plugin not exporting at all.** Confirm `diagnostics-otel` is in `plugins.allow`, the plugin is enabled, and both `diagnostics.enabled` and `diagnostics.otel.enabled` are `true`. **`protocol` ignored / nothing exported.** The `protocol` field must be `http/protobuf`. OpenClaw ignores gRPC. ## Configure with AI (experimental) If you'd rather have an OpenClaw up to Bronto for you itself, paste one of the prompts below into an agent with access to your OpenClaw host (or your local checkout of `~/.openclaw/`). Substitute occurrences of `` with your Bronto API key before sending. **Treat AI-generated configuration as untrusted until you've verified it.** **This approach is not recommended. Use at the risk of wasting your time** Coding agents routinely: * mis-substitute secrets (drop characters from the API key, wrap it in extra quotes, or leave the literal placeholder `` in place); * hallucinate config keys, env-var names, CLI flags, or endpoint paths that look plausible but don't exist; * skip steps, run them out of order, or silently overwrite parts of `openclaw.json` / `.env` that they think are irrelevant. After the agent finishes, **diff what changed**, open `~/.openclaw/.env` and `otel-collector-config.yaml` (if using the Collector), and confirm by hand that the API key, region, and field names match this page exactly. If telemetry doesn't show up in Bronto, start with [Troubleshooting](#troubleshooting) - and assume the agent's work is the cause until proven otherwise. ````text theme={"dark"} **Set up OpenTelemetry collection from OpenClaw and forward it to Bronto.** **Bronto details:** - API Key: `` - Region: EU - Log dataset: `openclaw` - Log collection: `openclaw-demo` - Service name: `openclaw-gateway` **Steps:** 1. Install and enable the `diagnostics-otel` plugin: ``` openclaw plugins install clawhub:@openclaw/diagnostics-otel openclaw plugins enable diagnostics-otel ``` 2. Add the `diagnostics` block to `~/.openclaw/openclaw.json` (top level, merge with existing — don't nuke anything): ```json { "diagnostics": { "enabled": true, "otel": { "enabled": true, "endpoint": "https://ingestion.eu.bronto.io", "tracesEndpoint": "https://ingestion.eu.bronto.io/v1/traces", "logsEndpoint": "https://ingestion.eu.bronto.io/v1/logs", "metricsEndpoint": "https://ingestion.eu.bronto.io/v1/metrics", "protocol": "http/protobuf", "serviceName": "openclaw-gateway", "headers": { "x-bronto-api-key": "${BRONTO_API_KEY}", "x-bronto-dataset": "openclaw", "x-bronto-collection": "openclaw-demo" }, "captureContent": true, "traces": true, "logs": true, "metrics": true, "sampleRate": 1, "flushIntervalMs": 10000 } } } ``` 3. Set up `~/.openclaw/.env` — add (don't overwrite existing vars): ``` BRONTO_API_KEY= OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta ``` 4. Restart the gateway. **Important:** Merge configs — don't clobber existing `openclaw.json` or `.env` contents. Read first, then update. ```` ````text theme={"dark"} **Set up OpenTelemetry collection from OpenClaw with an OTel Collector sidecar and forward it to Bronto.** **Bronto details:** - API Key: `` - Region: EU - Log dataset: `openclaw` - Log collection: `openclaw-demo` - Service name: `openclaw-gateway` **Steps:** 1. Install and enable the `diagnostics-otel` plugin: ``` openclaw plugins install clawhub:@openclaw/diagnostics-otel openclaw plugins enable diagnostics-otel ``` 2. Create an OpenTelemetry Collector config file (e.g. `otel-collector-config.yaml`) with the following content. This accepts OTLP/HTTP on port `4318`, prints everything to stdout via the `debug` exporter (useful for confirming signals are flowing — remove it once telemetry is stable), and forwards everything to Bronto: ```yaml receivers: otlp: protocols: http: endpoint: "0.0.0.0:4318" processors: batch: exporters: debug: verbosity: detailed otlphttp/brontotraces: traces_endpoint: "https://ingestion.eu.bronto.io/v1/traces" compression: gzip headers: x-bronto-api-key: otlphttp/brontometrics: metrics_endpoint: "https://ingestion.eu.bronto.io/v1/metrics" compression: gzip headers: x-bronto-api-key: otlphttp/brontologs: logs_endpoint: "https://ingestion.eu.bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: x-bronto-dataset: openclaw x-bronto-collection: openclaw-demo service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [debug, otlphttp/brontotraces] metrics: receivers: [otlp] processors: [batch] exporters: [debug, otlphttp/brontometrics] logs: receivers: [otlp] processors: [batch] exporters: [debug, otlphttp/brontologs] ``` 3. Start the OTel Collector with this config. Install method varies (Docker, Homebrew, Linux package, Kubernetes — see [OTel Collector installation docs](https://opentelemetry.io/docs/collector/installation/)). Example with Docker: ``` docker run --rm -p 4318:4318 -v $(pwd)/otel-collector-config.yaml:/etc/otelcol/config.yaml otel/opentelemetry-collector:latest --config=/etc/otelcol/config.yaml ``` 4. Add the `diagnostics` block to `~/.openclaw/openclaw.json` (top level, merge with existing — don't nuke anything): ```json { "diagnostics": { "enabled": true, "otel": { "enabled": true, "endpoint": "http://localhost:4318", "protocol": "http/protobuf", "serviceName": "openclaw-gateway", "captureContent": true, "traces": true, "logs": true, "metrics": true, "sampleRate": 1, "flushIntervalMs": 10000 } } } ``` If the Collector and gateway run as separate Docker containers on a shared network, change `endpoint` to the Collector's service/container name (e.g. `http://otel-collector:4318`). 5. Add the following to `~/.openclaw/.env` (merge — don't overwrite existing vars): ``` OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta ``` 6. Restart the gateway: ``` openclaw gateway restart ``` ```` Hand the agent this prompt if telemetry isn't showing up in Bronto after running one of the setup prompts above. ````text theme={"dark"} ### Step 1: Isolate where the failure is **If using an OTel Collector sidecar:** 1. Tail the Collector's stdout/logs. 2. Send the assistant a message. 3. Check what appears: - Signals appear in Collector output but **not** in Bronto → failure is between Collector and Bronto (check API key, region, headers in `otel-collector-config.yaml`). - Signals **don't appear** in Collector output at all → failure is upstream (plugin not enabled, gateway not restarted, no model activity). **If sending telemetry directly (no Collector):** Test network and auth (step 2 below). If that fails, switch to a Collector setup — it's the fastest way to narrow down where the pipeline breaks. Without it, you can't see what OpenClaw is (or isn't) emitting. ### Step 2: Network and auth test Run these from the same host as the Collector (or the OpenClaw gateway if sending directly). Region is EU — swap to `us` if needed. **DNS resolution** — empty output means DNS is broken (corporate VPN, misconfigured `resolv.conf`, captive portal, etc.): ```bash dig +short ingestion.eu.bronto.io ``` ### Step 3: Check common issues Go through these in order: | Symptom | Likely cause | Fix | |---------|-------------|-----| | No data at all | API key mangled (AI agents love to drop chars, add extra quotes, or replace with ``) | Re-paste the key by hand, confirm it matches exactly | | Logs arrive but no traces or metrics | Known intermittent issue with `diagnostics-otel` plugin | Fully restart the gateway service (not just a reload) — `docker compose restart openclaw-gateway` or restart the container/supervised process | | Traces arrive but no logs | `logs` toggle defaults to `false` in some plugin versions | Set `"logs": true` explicitly in `openclaw.json` | | Wrong region errors | API key is region-scoped — EU keys don't work against US endpoints and vice versa | Confirm key's region in Bronto, use matching `ingestion..bronto.io` | | Spans arrive but missing `gen_ai.*` attributes | Missing semconv opt-in | Set `OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental` in `~/.openclaw/.env` and restart gateway | | No prompt/response content on spans | `captureContent` not enabled | Set `"captureContent": true` in `diagnostics.otel` block | | Plugin not exporting at all | Plugin not properly enabled | Confirm `diagnostics-otel` is in `plugins.allow`, plugin is enabled, and both `diagnostics.enabled` and `diagnostics.otel.enabled` are `true` | | `protocol` ignored / nothing exported | Wrong protocol value | `protocol` must be `http/protobuf` — OpenClaw ignores gRPC | **Important:** Read `openclaw.json` and `.env` before making changes. Merge — don't nuke existing config. ```` # Vibe Building with Bronto Source: https://docs.bronto.io/ai-features/vibe-building Build custom observability interfaces with Lovable, v0, and Bronto APIs for workflows such as usage dashboards, service maps, and focused operational views. ## Overview You can build a custom service map, focused operational view, or workflow-specific interface on top of Bronto data. In this context, **vibe building** means using AI-assisted UI generation tools such as [Lovable](https://lovable.dev) and [v0](https://v0.dev) to build a frontend quickly while Bronto provides the observability data and APIs behind it. The fastest way to start is to remix Bronto's [Lovable baseline template](https://lovable.dev/projects/af3702ca-a831-411d-9620-789e05cf8e20), which already wires up Search, tracing, dashboards, and usage views against the Bronto API. If you prefer Vercel, the [BrontoVibe v0 example](https://v0-brontovibe.vercel.app/) is a deploy-your-own version of the same idea — ship it to Vercel, then refine it with the v0 agent in the Vercel platform using natural-language prompts. For a full walkthrough, see the [BrontoVibe blog post](https://bronto.io/blog/brontovibe). The examples on this page are starting points, not limits. Once you can query Bronto data and shape it into a UI, you can build many different workflow-specific experiences on top of the platform. ## Prerequisites This guide assumes you already have a Bronto account and have sent data to Bronto. If you haven't ingested data yet, [set up an agent](/agent-setup/agent-intro) first. You will also need: * a **Bronto API key** with access to the features your interface uses. The baseline template uses Search, tracing, dashboards, and usage, so generate a key with full access. See [API Keys](/Account-Management/API-Keys). * a UI generation or app-building tool such as [Lovable](https://lovable.dev) or [v0](https://v0.dev), or your own frontend stack. ## When to use this approach Vibe building works best when you want to create a workflow-specific experience on top of Bronto data, for example: * a team-specific dashboard * a customer or tenant-specific operational view * a custom service map that links directly into your investigation workflow This approach works especially well when you want to simplify a repeated workflow, present only the most relevant data for one audience, or embed observability into another tool. ## Core building blocks Most custom interfaces built on top of Bronto use a small set of platform concepts. See the [glossary](/getting-started/glossary) for full definitions: * [API Key](/getting-started/glossary#api-key) — authenticate your custom UI or internal app * [Search](/getting-started/glossary#search) — query Bronto data for custom tables, charts, filtered views, and workflow screens * [My Data](/getting-started/glossary#my-data) — understand datasets, ingestion, and search usage * [Dataset](/getting-started/glossary#dataset) — the unit of log storage your log queries run against * [Trace](/getting-started/glossary#trace) — derive service maps and trace-linked workflows from OpenTelemetry data ## Recommended setup flow Remix Bronto's [Lovable baseline template](https://lovable.dev/projects/af3702ca-a831-411d-9620-789e05cf8e20) to start with Search, tracing, dashboards, and usage already wired up. To deploy your own to Vercel instead, start from the [BrontoVibe v0 example](https://v0-brontovibe.vercel.app/) and refine it with the v0 agent in the Vercel platform using natural-language prompts. Create a dedicated [API key](/Account-Management/API-Keys) for the app and give it access to the features your interface uses. Describe the workflow-specific interface you want and let the tool generate it on top of Bronto data. See [Recommended prompt inputs](#recommended-prompt-inputs) for what to include. Keep the custom UI focused. When users need more context, link them back to Bronto search or trace exploration. ## Recommended prompt inputs When using Lovable or v0, prompts work best when they clearly define: * the user or team the UI is for * the exact workflow the UI should support * which Bronto API should supply the data * the filters, charts, tables, or graph views the page should include * where the UI should link back into Bronto ## Example: user-built custom service map A strong pattern is a custom service map built with Lovable on top of OpenTelemetry trace data already in Bronto. This is useful when you want a workflow-specific topology view instead of a general-purpose tracing UI. For example, a team may want to highlight only production services, emphasize error-heavy edges, or make each node link into a trace investigation flow. What this usually looks like in practice: * a node graph of services and dependencies * edge labels showing call volume or protocol * color or emphasis based on latency or error rate * a side panel for the selected service * direct links into traces or related logs Typical elements include: * nodes for services, queues, gateways, and external dependencies * edges representing calls between services * span count, average latency, and error rate on each node or edge * filters for environment, time range, transaction type, or service group * click-through actions that open traces or related logs for the selected service Here is an example of a service-flow view a Bronto user built with Lovable on top of trace data already stored in Bronto: Example custom service map built with Lovable on top of Bronto trace data ### Example prompt ```text theme={"dark"} Build a custom service map for Bronto. Use OpenTelemetry trace data in Bronto to derive service-to-service relationships. Render services and dependencies as a graph. Display latency, span volume, and error rate on nodes and edges. Support filtering by environment and time range. Include a side panel that links from a selected service to trace and log investigation views in Bronto. ``` ## Additional examples The same setup pattern can support many other interfaces beyond the main example above. ### Usage and cost view While Bronto already includes in-product usage tooling, some teams may still want to embed usage and cost data into another internal tool, team portal, or customer-specific view using the [Usage API](/api-reference/usage/overview). ```text theme={"dark"} Build a usage and cost view on top of the Bronto Usage API. Show ingestion and search usage for a selected team or environment. Include a trend chart, top datasets, and threshold indicators. Keep the layout compact and easy to embed into another internal page. ``` ### Support-facing operational view A support team can build a focused screen that shows recent customer-facing errors, affected services, and links into the relevant logs or traces without exposing the full Bronto experience to every user. ```text theme={"dark"} Build a support-facing operational dashboard for Bronto. Show recent production errors, top affected services, and links to related traces. Add filters for environment, customer segment, and severity. Keep the layout simple and optimized for quick triage during support workflows. ``` ### Release-health screen A delivery or platform team can build a deployment-window view that focuses on regressions immediately after a release, combining search results, error trends, and service-level indicators in one place. ```text theme={"dark"} Build a release-health screen on top of Bronto. Show errors, latency changes, and affected services for a selected deployment window. Include a time-series chart, a recent errors table, and links into detailed Bronto searches. Make the page easy to scan during release validation. ``` ## Best practices * start with one narrow workflow instead of trying to recreate the full Bronto UI * create a dedicated API key for each custom app * link back into Bronto whenever users need deeper context or broader exploration # Check if user or group has access to org Source: https://docs.bronto.io/api-reference/access/check-if-user-or-group-has-access-to-org https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /organizations/{orgId}/access/{entityType}/{entityId}/check # Grant access to a user or group Source: https://docs.bronto.io/api-reference/access/grant-access-to-a-user-or-group https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /organizations/{orgId}/access/{entityType}/{entityId} # List all members who have access to this organization Source: https://docs.bronto.io/api-reference/access/list-all-members-who-have-access-to-this-organization https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /organizations/{orgId}/access # Revoke access from a user or group Source: https://docs.bronto.io/api-reference/access/revoke-access-from-a-user-or-group https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /organizations/{orgId}/access/{entityType}/{entityId} # Switch active organization for a user Source: https://docs.bronto.io/api-reference/access/switch-active-organization-for-a-user https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /organizations/{orgId}/access/user/{userId}/switch Sets the specified organization as the active organization for the user. The user must already have access to this organization. # Ask AI to give hints regarding a particular error Source: https://docs.bronto.io/api-reference/ai/ask-ai-to-give-hints-regarding-a-particular-error https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /explain-error # Ask AI to provide a widget based on a prompt request Source: https://docs.bronto.io/api-reference/ai/ask-ai-to-provide-a-widget-based-on-a-prompt-request https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /widget-creation-assistant # Create a new API key Source: https://docs.bronto.io/api-reference/api-keys/create-a-new-api-key post /api-keys Create a new Bronto API key with one or more role scopes such as IngestionApi or SearchApi, and an optional TTL, for authenticating REST API requests. # Delete an API key Source: https://docs.bronto.io/api-reference/api-keys/delete-an-api-key delete /api-keys/{apiKeyId} Revoke a Bronto API key by its unique identifier to immediately invalidate it so any clients still using it can no longer authenticate REST API requests. # API Key Authentication Source: https://docs.bronto.io/api-reference/api-keys/overview Authenticate Bronto API requests with API keys passed in the X-BRONTO-API-KEY header. Roles assigned to each key control which endpoints are available. # Retrieve a list of API keys Source: https://docs.bronto.io/api-reference/api-keys/retrieve-a-list-of-api-keys get /api-keys List every Bronto API key in your organization with its name, assigned roles, creation time, and TTL so you can audit and rotate keys. # Update an API key Source: https://docs.bronto.io/api-reference/api-keys/update-an-api-key patch /api-keys/{apiKeyId} Update the name, role assignments, or expiration of an existing Bronto API key without rotating the key value or breaking active integrations. # Retrieve a list of collections Source: https://docs.bronto.io/api-reference/collections/retrieve-a-list-of-collections https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /collections # Retrieve contextual information for a given sequence and log Source: https://docs.bronto.io/api-reference/context/get-context get /context Retrieve the log events immediately before, after, or surrounding a specific event of interest to investigate incidents and reconstruct request timelines. # Context API Source: https://docs.bronto.io/api-reference/context/overview Use the Bronto Context REST API to retrieve log events surrounding a specific event of interest, before, after, or both, for faster troubleshooting. # Retrieve contextual information for a given sequence and log Source: https://docs.bronto.io/api-reference/context/retrieve-contextual-information-for-a-given-sequence-and-log https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /context # Get the customer record for the current organization Source: https://docs.bronto.io/api-reference/customers/get-the-customer-record-for-the-current-organization https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /customer # Update the customer record for the current organization Source: https://docs.bronto.io/api-reference/customers/update-the-customer-record-for-the-current-organization https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml patch /customer # Append widgets to a dashboard Source: https://docs.bronto.io/api-reference/dashboards/append-widgets-to-a-dashboard https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /dashboards/{dashboardId}/widgets # Create a dashboard Source: https://docs.bronto.io/api-reference/dashboards/create-a-dashboard https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /dashboards # Delete a dashboard by ID Source: https://docs.bronto.io/api-reference/dashboards/delete-a-dashboard-by-id https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /dashboards/{dashboardId} # Detach a dashboard from a template Source: https://docs.bronto.io/api-reference/dashboards/detach-a-dashboard-from-a-template https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /dashboards/{dashboardId}/detach-from-template # Get a single Dashboard by ID Source: https://docs.bronto.io/api-reference/dashboards/get-a-single-dashboard-by-id https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /dashboards/{dashboardId} # Get all dashboards for an organisation Source: https://docs.bronto.io/api-reference/dashboards/get-all-dashboards-for-an-organisation https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /dashboards # List dashboards associated with a log Source: https://docs.bronto.io/api-reference/dashboards/list-dashboards-associated-with-a-log https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /logs/{logId}/dashboards # Partially update a dashboard by ID, allowing either a name change or modification of widget IDs (append or remove) Source: https://docs.bronto.io/api-reference/dashboards/partially-update-a-dashboard-by-id-allowing-either-a-name-change-or-modification-of-widget-ids-append-or-remove https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml patch /dashboards/{dashboardId} # Remove a widget from a dashboard Source: https://docs.bronto.io/api-reference/dashboards/remove-a-widget-from-a-dashboard https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /dashboards/{dashboardId}/widgets/{widgetId} # Assign a parser to a dataset Source: https://docs.bronto.io/api-reference/datasets/assign-a-parser-to-a-dataset https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml put /datasets/{datasetId}/parser # Create a new dataset Source: https://docs.bronto.io/api-reference/datasets/create-a-new-dataset https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /datasets # Get the parser assigned to a dataset Source: https://docs.bronto.io/api-reference/datasets/get-the-parser-assigned-to-a-dataset https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /datasets/{datasetId}/parser # Resolve data sets Source: https://docs.bronto.io/api-reference/datasets/resolve-data-sets https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /datasets/resolve Resolve datasets based on criteria such as keys and "from" expressions # Retrieve a list of datasets Source: https://docs.bronto.io/api-reference/datasets/retrieve-a-list-of-datasets https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /datasets # Unassign the parser from a dataset Source: https://docs.bronto.io/api-reference/datasets/unassign-the-parser-from-a-dataset https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /datasets/{datasetId}/parser # Create a new monitor downtime Source: https://docs.bronto.io/api-reference/downtimes/create-a-new-monitor-downtime https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /monitors/downtimes Create a downtime to silence monitors periodically # Delete a monitor downtime Source: https://docs.bronto.io/api-reference/downtimes/delete-a-monitor-downtime https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /monitors/downtimes/{downtimeId} # Retrieve all monitor downtimes Source: https://docs.bronto.io/api-reference/downtimes/retrieve-all-monitor-downtimes https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /monitors/downtimes Retrieves the list of currently configured downtimes # Update a monitor downtime Source: https://docs.bronto.io/api-reference/downtimes/update-a-monitor-downtime https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml put /monitors/downtimes/{downtimeId} update an existing downtime # Create a new encryption key Source: https://docs.bronto.io/api-reference/encryption-keys/create-a-new-encryption-key https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /encryption-keys # Delete an encryption key Source: https://docs.bronto.io/api-reference/encryption-keys/delete-an-encryption-key https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /encryption-keys/{keyId} Delete an encryption key. Keys can only be deleted when their status is CREATED. # Retrieve a list of encryption keys Source: https://docs.bronto.io/api-reference/encryption-keys/retrieve-a-list-of-encryption-keys https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /encryption-keys # Retrieve a specific encryption key Source: https://docs.bronto.io/api-reference/encryption-keys/retrieve-a-specific-encryption-key https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /encryption-keys/{keyId} # Update an existing encryption key Source: https://docs.bronto.io/api-reference/encryption-keys/update-an-existing-encryption-key https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml patch /encryption-keys/{keyId} Update an encryption key's display name and/or status. Only name and status can be updated. Status can only transition from CREATED to ACTIVE. # return the list of monitor events Source: https://docs.bronto.io/api-reference/events/return-the-list-of-monitor-events https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /monitors/{monitorId}/events # Create a new export Source: https://docs.bronto.io/api-reference/exports/create-a-new-export post /exports Creates an export from either explicit log ids in `from` or a dataset selector in `from_expr`. When `from_expr` is supplied, it is resolved at creation time and the resulting log ids are persisted in `search_details.from` for export processing. # Delete an export by ID Source: https://docs.bronto.io/api-reference/exports/delete-an-export delete /exports/{exportId} Delete a Bronto export job by ID to cancel an in-progress export or remove the download URL for a completed export from your organization. # Delete an export by ID Source: https://docs.bronto.io/api-reference/exports/delete-an-export-by-id https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /exports/{exportId} # Retrieve an export by ID Source: https://docs.bronto.io/api-reference/exports/get-export-by-id get /exports/{exportId} Poll the status and progress percentage of an asynchronous Bronto export job by ID, and retrieve the signed download URL once the export completes. # Exports API Source: https://docs.bronto.io/api-reference/exports/overview Use the Bronto Exports REST API to download large volumes of log data asynchronously, filtered by query, with status polling and direct download URLs. The Bronto Export API allows you to efficiently download large volumes of log data for further analysis. The data to be exported can be filtered by entering the search parameters "from", "where" and "time\_range" as per a normal query in the "search\_details" object. To export data the following steps are required: 1. Create an export using a POST request, which will return an "export\_id", "status" and "progress". 2. Use the export id to get the status of the export task by sending a GET request, which will return "status" and "progress" with a value of percentage completed. When the export is completed, the "status" will be "COMPLETE" 3. Once the export task has completed you can download your data using curl (or similar) from the "location" URL returned in the GET response. # Retrieve a list of exports Source: https://docs.bronto.io/api-reference/exports/retrieve-a-list-of-exports get /exports List every Bronto data export job in your organization, including IDs, statuses, and progress, so you can monitor running exports and access past downloads. # Retrieve an export by ID Source: https://docs.bronto.io/api-reference/exports/retrieve-an-export-by-id https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /exports/{exportId} # Create a new forward config to archive your logs in another system Source: https://docs.bronto.io/api-reference/forward/create-a-new-forward-config-to-archive-your-logs-in-another-system https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /forward-configs Create a forward config, to forward log events outside the Bronto system (e.g. archive logs in an S3 bucket) # Create a new forward config to archive your logs in another system Source: https://docs.bronto.io/api-reference/forward/create-new-config post /forward-configs Create a forward config, to forward log events outside the Bronto system (e.g. archive logs in an S3 bucket) This feature allows users to forward log events outside of Bronto. A common use case would be archiving your log data to an AWS S3 bucket. # Delete a forward config Source: https://docs.bronto.io/api-reference/forward/delete-a-config delete /forward-configs/{forwardId} Delete a Bronto log forwarding configuration by ID to stop archiving matching log events to the configured S3, GCS, or HTTP destination. # Delete a forward config Source: https://docs.bronto.io/api-reference/forward/delete-a-forward-config https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /forward-configs/{forwardId} # Retrieve forward configs Source: https://docs.bronto.io/api-reference/forward/retrieve-forward-configs get /forward-configs Retrieves the list of all forward configs set up for the account # Test access to the destination Source: https://docs.bronto.io/api-reference/forward/test-access-to-destination post /forward-configs/test-destination Check access to the destination. A test file will be created and deleted to make sure Bronto can access your destination # Test access to the destination Source: https://docs.bronto.io/api-reference/forward/test-access-to-the-destination https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /forward-configs/test-destination Check access to the destination. A test file will be created and deleted to make sure Bronto can access your destination # Update an existing forward config Source: https://docs.bronto.io/api-reference/forward/update-an-existing-forward-config https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml put /forward-configs/{forwardId} Update a forward config, to forward log events outside the Bronto system (e.g. archive logs in an S3 bucket) # Update an existing forward config Source: https://docs.bronto.io/api-reference/forward/update-existing-config put /forward-configs/{forwardId} Update a forward config, to forward log events outside the Bronto system (e.g. archive logs in an S3 bucket) # Add members to a group Source: https://docs.bronto.io/api-reference/groups/add-members-to-a-group https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /groups/{groupId}/members # Create a new group Source: https://docs.bronto.io/api-reference/groups/create-a-new-group https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /groups # Delete a group Source: https://docs.bronto.io/api-reference/groups/delete-a-group https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /groups/{groupId} # Get a specific group Source: https://docs.bronto.io/api-reference/groups/get-a-specific-group https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /groups/{groupId} # List all user groups in the organization Source: https://docs.bronto.io/api-reference/groups/list-all-user-groups-in-the-organization https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /groups # List groups a member belongs to Source: https://docs.bronto.io/api-reference/groups/list-groups-a-member-belongs-to https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /users/{userId}/groups # List members of a group Source: https://docs.bronto.io/api-reference/groups/list-members-of-a-group https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /groups/{groupId}/members # Remove members from a group Source: https://docs.bronto.io/api-reference/groups/remove-members-from-a-group https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /groups/{groupId}/members # Update a group Source: https://docs.bronto.io/api-reference/groups/update-a-group https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml patch /groups/{groupId} # Create a Slack Integration Resource Source: https://docs.bronto.io/api-reference/integrations/create-a-slack-integration-resource https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /integrations/slack # Create a Webhook Integration Resource Source: https://docs.bronto.io/api-reference/integrations/create-a-webhook-integration-resource https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /integrations/webhooks # Delete a Slack Integration Resource Source: https://docs.bronto.io/api-reference/integrations/delete-a-slack-integration-resource https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /integrations/slack/{slack_id} # Delete a Slack workspace resource; note this does not uninstall the bronto.io app from Slack Source: https://docs.bronto.io/api-reference/integrations/delete-a-slack-workspace-resource;-note-this-does-not-uninstall-the-brontoio-app-from-slack https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /integrations/slack/workspaces/{workspace_id} # Delete a webhook Integration Resource Source: https://docs.bronto.io/api-reference/integrations/delete-a-webhook-integration-resource https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /integrations/webhooks/{webhook_id} # Get all Slack Integration Resources for an organisation Source: https://docs.bronto.io/api-reference/integrations/get-all-slack-integration-resources-for-an-organisation https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /integrations/slack # Get all Slack workspace resources for an organisation Source: https://docs.bronto.io/api-reference/integrations/get-all-slack-workspace-resources-for-an-organisation https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /integrations/slack/workspaces # Get all Webhook Integration Resources for an organisation Source: https://docs.bronto.io/api-reference/integrations/get-all-webhook-integration-resources-for-an-organisation https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /integrations/webhooks # Update a Slack Integration Resource Source: https://docs.bronto.io/api-reference/integrations/update-a-slack-integration-resource https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml put /integrations/slack/{slack_id} # Update a webhook Integration Resource Source: https://docs.bronto.io/api-reference/integrations/update-a-webhook-integration-resource https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml put /integrations/webhooks/{webhook_id} # Bronto API Source: https://docs.bronto.io/api-reference/introduction https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml Manage logs, run searches, control users and access, and automate workflows in Bronto using a RESTful API authenticated with API keys or bearer tokens. # Bronto API The **Bronto API** is a RESTful interface for managing logs, monitoring system activity, and automating key workflows within the Bronto platform. ## Overview The Bronto API enables developers and engineering teams to: * **Retrieve data** with flexible querying and filtering * **Manage users** and control access programmatically * **Monitor systems** and automate operational workflows * **Control log retention** policies and visualization settings ## Base Information | Property | Value | | - | - | | API Version | 1.0.0 | | Protocol | HTTPS | | Style | RESTful | | License | Commercial | | Auth | API Key / Bearer Token | ## OpenAPI Specification The full machine-readable specification is available for download or direct consumption by API clients and LLM tools. ## Key Capabilities ### Log Management Search and manage log data at scale. ### Data Retrieval Query and filter log data with precision. Retrieve results in real time or batch mode depending on your use case. ### User & Access Management Create and manage users, assign roles, and control permissions programmatically across your organisation. ### System Monitoring Access system health metrics, activity feeds, and operational data to power dashboards and alerting pipelines. ### Automation & Workflows Integrate the Bronto API into CI/CD pipelines, observability stacks, or internal tooling to reduce manual overhead. ## Getting Started 1. **Obtain credentials** — Sign in to Bronto and create a new [API key](https://docs.bronto.io/Account-Management/API-Keys). 2. **Review the OpenAPI spec** — Download the YAML above or explore the interactive reference in the sidebar. 3. **Make your first request** — Use any HTTP client (curl, Postman, SDKs) against the base URL. 4. **Explore the guides** — See the sidebar for authentication, pagination, error handling, and endpoint references. ## Licensing License: `Commercial` # Create a new limit Source: https://docs.bronto.io/api-reference/limits/create-a-new-limit https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /limits Create a limit # Delete a limit by ID Source: https://docs.bronto.io/api-reference/limits/delete-a-limit-by-id https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /limits/{limitId} # Get a Limit Source: https://docs.bronto.io/api-reference/limits/get-a-limit https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /limits/{limitId} # Retrieve limits Source: https://docs.bronto.io/api-reference/limits/retrieve-limits https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /limits Retrieves the list of limits configured for the organisation. Limits define thresholds and constraints applied to resources within your account. # Update a limit Source: https://docs.bronto.io/api-reference/limits/update-a-limit https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml patch /limits/{limitId} update an existing limit # Initiate a live tail job Source: https://docs.bronto.io/api-reference/live-tail/initiate-a-live-tail-job https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /live-tail # Poll a live tail job Source: https://docs.bronto.io/api-reference/live-tail/poll-a-live-tail-job https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /live-tail # Create a new log Source: https://docs.bronto.io/api-reference/logs/create-a-new-log https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /logs # Create a new log Source: https://docs.bronto.io/api-reference/logs/create-log post /logs Create a new Bronto log dataset to receive timestamped events, with a configurable name, parser, retention, and metadata for routing ingested data. # Retrieve a list of logs Source: https://docs.bronto.io/api-reference/logs/get-logs get /logs Retrieve the list of log datasets in your Bronto organization with metadata such as IDs, names, and retention settings to inspect or build search queries. # Logs API Source: https://docs.bronto.io/api-reference/logs/overview Use the Bronto Logs REST API to create new log datasets and retrieve metadata for logs that can be searched, filtered, and aggregated across your organization. # Retrieve a list of log views Source: https://docs.bronto.io/api-reference/logs/retrieve-a-list-of-log-views https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /logs/views # Retrieve a list of logs Source: https://docs.bronto.io/api-reference/logs/retrieve-a-list-of-logs https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /logs # Retrieve the list of metrics metadata sent to Bronto Source: https://docs.bronto.io/api-reference/metrics/retrieve-the-list-of-metrics-metadata-sent-to-bronto https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /metrics # Retrieve the metadata of an ingested metric Source: https://docs.bronto.io/api-reference/metrics/retrieve-the-metadata-of-an-ingested-metric https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /metrics/{metric_id} # Retrieve the top keys and sample values for a metric Source: https://docs.bronto.io/api-reference/metrics/retrieve-the-top-keys-and-sample-values-for-a-metric https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /metrics/{metric_id}/top-keys Returns the keys (attributes) received for a metric within a time window, together with each key's data type and a sample of the values seen for it. Use this to discover which dimensions you can filter or group a metric by. Set the time window in one of two ways: - `time_range`, a relative range such as `last 20 minutes`, **or** - `from_ts` and `to_ts` together, as an absolute range in Unix milliseconds. If no time window is provided, the most recent keys and values are returned. The response is an object keyed by key name. Values are a sample, not an exhaustive list. # Create a new monitor Source: https://docs.bronto.io/api-reference/monitors/create-a-new-monitor https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /monitors Create a monitor to be notified when a log-based or metric-based condition is met # Create a new monitor template Source: https://docs.bronto.io/api-reference/monitors/create-a-new-monitor-template https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /monitors/templates Create a monitor template to be notified when a log-based or metric-based condition is met # Delete a monitor Source: https://docs.bronto.io/api-reference/monitors/delete-a-monitor https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /monitors/{monitorId} # Delete a monitor template Source: https://docs.bronto.io/api-reference/monitors/delete-a-monitor-template https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /monitors/templates/{templateId} # Get a monitor Source: https://docs.bronto.io/api-reference/monitors/get-a-monitor https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /monitors/{monitorId} # Get a monitor template Source: https://docs.bronto.io/api-reference/monitors/get-a-monitor-template https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /monitors/templates/{templateId} # List monitors associated with a log Source: https://docs.bronto.io/api-reference/monitors/list-monitors-associated-with-a-log https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /logs/{logId}/monitors # Retrieve monitor templates Source: https://docs.bronto.io/api-reference/monitors/retrieve-monitor-templates https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /monitors/templates Retrieves the list of monitor templates # Retrieve monitors Source: https://docs.bronto.io/api-reference/monitors/retrieve-monitors https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /monitors Retrieves the list of currently configured monitors # return the list of monitor notifications Source: https://docs.bronto.io/api-reference/monitors/return-the-list-of-monitor-notifications https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /monitors/{monitorId}/notifications # Update a monitor Source: https://docs.bronto.io/api-reference/monitors/update-a-monitor https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml put /monitors/{monitorId} Update an existing monitor # Update a monitor template Source: https://docs.bronto.io/api-reference/monitors/update-a-monitor-template https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml put /monitors/templates/{templateId} Update an existing monitor template # Update monitor status Source: https://docs.bronto.io/api-reference/monitors/update-monitor-status https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /monitors/{monitorId}/status Update the status of a monitor - only supports muting/unmuting # Get Pattern templates for logs matching search criteria Source: https://docs.bronto.io/api-reference/patterns/get-pattern-templates-for-logs-matching-search-criteria https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /patterns Returns the Pattern IDs, templates, and source log ID for all logs matching the given search criteria. # Retrieve permissions Source: https://docs.bronto.io/api-reference/permissions/retrieve-permissions https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /permissions Retrieves a list of all available permissions grouped by resource. Permissions define the individual actions that can be performed within the system, such as reading API keys or managing monitors. Permissions are assigned to roles, which in turn are assigned to users and API keys. Use the `/roles` endpoint to see how permissions are grouped into roles. # List policies by resource Source: https://docs.bronto.io/api-reference/policies/list-policies-by-resource https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /policies/resources/{resource_type}/{resource_id} # Create a new role Source: https://docs.bronto.io/api-reference/roles/create-a-new-role https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /roles Creates a new role with specified permissions in the organization. Roles define sets of permissions that can be assigned to users to control their access to various system features and resources. The role must have a unique identifier and include at least one permission. # Delete a role Source: https://docs.bronto.io/api-reference/roles/delete-a-role https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /roles/{role_id} Deletes a role by its ID. # Retrieve a list of roles Source: https://docs.bronto.io/api-reference/roles/retrieve-a-list-of-roles https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /roles Retrieves a list of all roles in the organization along with their assigned permissions. A role groups together a set of permissions from the available permissions (see `/permissions`) and can be assigned to users and API keys to control access. Each role includes its full list of permissions, allowing you to understand exactly what actions a user or API key with that role can perform. # Retrieve a specific role Source: https://docs.bronto.io/api-reference/roles/retrieve-a-specific-role https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /roles/{role_id} Retrieves a specific role by its ID, including the full list of permissions assigned to it. Permissions define what actions users or API keys with this role can perform. See `/permissions` for the complete list of available permissions, and `/roles` to list all roles. # Update an existing role Source: https://docs.bronto.io/api-reference/roles/update-an-existing-role https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml put /roles/{role_id} Updates a role's properties and assigned permissions. # Cancel an asynchronous search Source: https://docs.bronto.io/api-reference/search/delete-search delete /search/status/{statusId} Cancel a long-running asynchronous Bronto search by its status identifier to stop the query and free up search capacity for other workloads. # Execute a query Source: https://docs.bronto.io/api-reference/search/execute-a-query https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /search You can execute queries on your log data by using Bronto's syntax based on a subset of SQL as described in the documentation https://docs.bronto.io/query-syntax/overview. Bronto supports both the GET and POST methods for executing a query, however the POST method is preferred as it avoids problems related to maximum URL length when the query parameters are very long. In the context of the REST API, there are three distinct types queries which determine which parts of the response object are populated: + Event search queries return a list of events matching the specified filter. The response will be paginated if more than `limit` (default 50) matching events are returned. + Aggregate queries apply aggregate functions such as count(), sum(), max(), avg() to your log data, and return a number or a timeseries of numbers. + Group by aggregate queries return numerical results grouped according to the values for the attributes specified in the group by clause. The query type is determined by the combination of the `select` and `groups` parameters. # Execute a query Source: https://docs.bronto.io/api-reference/search/execute-a-query-1 https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /search You can execute queries on your log data by using Bronto's syntax based on a subset of SQL as described in the documentation https://docs.bronto.io/query-syntax/overview Bronto supports both the GET and POST methods for executing a query, however the POST method is preferred as it avoids problems related to maximum URL length when the query parameters are very long. In the context of the REST API, there are three distinct types queries which determine which parts of the response object are populated: + Event search queries return a list of events matching the specified filter. The response will be paginated if more than `limit` (default 50) matching events are returned. + Aggregate queries apply aggregate functions such as count(), sum(), max(), avg() to your log data, and return a number or a timeseries of numbers. + Group by aggregate queries return numerical results grouped according to the values for the attributes specified in the group by clause. The query type is determined by the combination of the `select` and `groups` parameters. # Get asynchronous search status Source: https://docs.bronto.io/api-reference/search/get-search-status get /search/status/{statusId} Poll the status, progress, and partial results of an asynchronous Bronto search query by its status identifier to track long-running search jobs. # Execute a query Source: https://docs.bronto.io/api-reference/search/post-search post /search You can execute queries on your log data by using Bronto's syntax based on a subset of SQL as described in the documentation https://docs.bronto.io/query-syntax/overview Bronto supports both the GET and POST methods for executing a query, however the POST method is preferred as it avoids problems related to maximum URL length when the query parameters are very long. In the context of the REST API, there are three distinct types queries which determine which parts of the response object are populated: + Event search queries return a list of events matching the specified filter. The response will be paginated if more than `limit` (default 50) matching events are returned. + Aggregate queries apply aggregate functions such as count(), sum(), max(), avg() to your log data, and return a number or a timeseries of numbers. + Group by aggregate queries return numerical results grouped according to the values for the attributes specified in the group by clause. The query type is determined by the combination of the `select` and `groups` parameters. # Execute a query Source: https://docs.bronto.io/api-reference/search/search get /search You can execute queries on your log data by using Bronto's syntax based on a subset of SQL as described in the documentation https://docs.bronto.io/query-syntax/overview. Bronto supports both the GET and POST methods for executing a query, however the POST method is preferred as it avoids problems related to maximum URL length when the query parameters are very long. In the context of the REST API, there are three distinct types queries which determine which parts of the response object are populated: + Event search queries return a list of events matching the specified filter. The response will be paginated if more than `limit` (default 50) matching events are returned. + Aggregate queries apply aggregate functions such as count(), sum(), max(), avg() to your log data, and return a number or a timeseries of numbers. + Group by aggregate queries return numerical results grouped according to the values for the attributes specified in the group by clause. The query type is determined by the combination of the `select` and `groups` parameters. # Create a tag Source: https://docs.bronto.io/api-reference/tags/create-a-tag https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /tags Create a tag and associate it with an entity. # Delete a tag Source: https://docs.bronto.io/api-reference/tags/delete-a-tag https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /tags # List tags Source: https://docs.bronto.io/api-reference/tags/list-tags https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /tags/search Retrieve a list of tags, optionally filtered by name, value, or entity type. # Update a tag Source: https://docs.bronto.io/api-reference/tags/update-a-tag https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml put /tags Update the value of a tag. # Retrieve the timeseries for a metric definition. Source: https://docs.bronto.io/api-reference/timeseries/retrieve-the-timeseries-for-a-metric-definition https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /timeseries/{metric_definition_id} # Run an ad-hoc timeseries query Source: https://docs.bronto.io/api-reference/timeseries/run-an-ad-hoc-timeseries-query https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /timeseries/search Execute a one-off timeseries query or formula directly. This is not saved. Use for interactive mode or metrics explorer. # Retrieve top keys for logs Source: https://docs.bronto.io/api-reference/top-keys/get-top-keys get /top-keys Retrieves the most frequently occurring keys (field names) from log events within a specified time range. This is useful for understanding the structure and common fields present in your log data. If no log ID is specified, top keys are returned for all accessible logs. # Top Keys API Source: https://docs.bronto.io/api-reference/top-keys/overview Use the Bronto Top Keys REST API to retrieve the most frequent keys and values for a dataset to understand cardinality and inform query design. # Retrieve top keys for logs Source: https://docs.bronto.io/api-reference/top-keys/retrieve-top-keys-for-logs https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /top-keys Retrieves the most frequently occurring keys (field names) from log events within a specified time range. This is useful for understanding the structure and common fields present in your log data. If no log ID is specified, top keys are returned for all accessible logs. # Get the usage over a period of time for a log id. Source: https://docs.bronto.io/api-reference/usage/get-usage-for-log-id get /usage/organizations/logs Retrieve Bronto ingestion and search usage for a specific log dataset over a chosen timeframe to monitor costs, capacity, and billing trends per log ID. # Get the usage over a period of time for a user per log id. Source: https://docs.bronto.io/api-reference/usage/get-usage-for-user-per-log-id get /usage/users Retrieve Bronto ingestion and search volume broken down by user and log dataset over a chosen timeframe to attribute usage and identify heavy consumers. # Usage API Source: https://docs.bronto.io/api-reference/usage/overview Use the Bronto Usage REST API to track ingestion and search volume per dataset over a chosen timeframe and drill into per-user or per-log breakdowns. # Create a new user Source: https://docs.bronto.io/api-reference/users/create-a-new-user post /users Invite a new user to your Bronto organization with name, email, and an Admin, Standard, or ReadOnly role that controls their permissions across the platform. # Deactivate a user Source: https://docs.bronto.io/api-reference/users/deactivate-a-user https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /users/{userId}/deactivate # Delete a user by ID Source: https://docs.bronto.io/api-reference/users/delete-a-user-by-id delete /users/{userId} Permanently removes a user from the system. This action cannot be undone. All associated data and permissions for this user will be removed. Only administrators can delete users. # Retrieve a user by ID Source: https://docs.bronto.io/api-reference/users/get-a-single-user-by-id get /users/{userId} Retrieves detailed information for a specific user using their unique identifier. Returns all user attributes including profile information, roles, and status. # Get user preferences Source: https://docs.bronto.io/api-reference/users/get-user-preferences https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /users/{userId}/preferences Returns the stored user preferences for the specified organization and user. # List all organizations this user has access to Source: https://docs.bronto.io/api-reference/users/list-all-organizations-this-user-has-access-to https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /users/{userId}/access # Users API Source: https://docs.bronto.io/api-reference/users/overview Use the Bronto Users REST API to create, list, update, and delete users and assign Admin, Standard, or ReadOnly roles that control their permissions. * "Admin" role has permission for all actions on all entities in the application. * "Standard" role allows Read/Write and Delete actions on entities in non-sensitive areas of the application. * "ReadOnly" role allows only read actions and only on entities in non-sensitive areas of the application. # Patch user preferences Source: https://docs.bronto.io/api-reference/users/patch-user-preferences https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml patch /users/{userId}/preferences Sets or updates specific user preferences without overwriting others. # Reactivate a user Source: https://docs.bronto.io/api-reference/users/reactivate-a-user https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /users/{userId}/reactivate # Resend a user's invitation email Source: https://docs.bronto.io/api-reference/users/resend-a-users-invitation-email https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /users/{userId}/resend-invite # Retrieve a list of users Source: https://docs.bronto.io/api-reference/users/retrieve-a-list-of-users get /users List every user in your Bronto organization with their email, assigned role, and status to audit access or sync directory information into your tooling. # Retrieve a list of users Source: https://docs.bronto.io/api-reference/users/retrieve-a-list-of-users-1 https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /users/all # Retrieve a user by ID Source: https://docs.bronto.io/api-reference/users/retrieve-a-user-by-id https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /users/{userId} Retrieves detailed information for a specific user using their unique identifier. Returns all user attributes including profile information, roles, and status. # Update a user Source: https://docs.bronto.io/api-reference/users/update-a-user https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml patch /users/{userId} Updates the specified user's information. Only the fields provided in the request body will be modified; other fields will remain unchanged. Users can typically update their own profiles, while administrators may update any user. # Update a user Source: https://docs.bronto.io/api-reference/users/updates-a-user patch /users/{userId} Updates the specified user's information. Only the fields provided in the request body will be modified; other fields will remain unchanged. Users can typically update their own profiles, while administrators may update any user. # Append widgets to a widget Source: https://docs.bronto.io/api-reference/widgets/append-widgets-to-a-widget https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /widgets/{id}/widgets # Create a widget Source: https://docs.bronto.io/api-reference/widgets/create-a-widget https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml post /widgets # Delete a widget Source: https://docs.bronto.io/api-reference/widgets/delete-a-widget https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /widgets/{id} # Partially update a widget by ID Source: https://docs.bronto.io/api-reference/widgets/partially-update-a-widget-by-id https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml patch /widgets/{id} # Remove a widget from a widget Source: https://docs.bronto.io/api-reference/widgets/remove-a-widget-from-a-widget https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml delete /widgets/{id}/widgets/{widgetId} # Retrieve a widget Source: https://docs.bronto.io/api-reference/widgets/retrieve-a-widget https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /widgets/{id} # Retrieve all the widgets Source: https://docs.bronto.io/api-reference/widgets/retrieve-all-the-widgets https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml get /widgets # Update a widget Source: https://docs.bronto.io/api-reference/widgets/update-a-widget https://s3.eu-west-1.amazonaws.com/docs.brontobytes.io/redocusaurus/brontobytes.yaml put /widgets/{id} # Changelog Source: https://docs.bronto.io/changelog Read the latest Bronto product updates, new features, integrations, and announcements, with release notes for log management, tracing, and AI features. Bronto Tracing is now generally available. You can now send OpenTelemetry traces to Bronto, explore service and operation health, and investigate latency, errors, and trace volume from the Tracing UI. To get started, see [Send Traces to Bronto](/tracing/send-traces) and [Explore Traces](/tracing/explore-traces). # Change Detection Monitors Source: https://docs.bronto.io/core-features/change-detection Detect spikes, drops, and shifts in metrics or telemetry with Bronto change detection monitors that compare current values against historical baselines. Change detection monitors allow you to receive alerts when the value of a query changes significantly compared to a previous point in time. This feature is useful for catching unexpected spikes, drops, or shifts in your data trends. ## Creating a Change Detection Monitor To create a change detection monitor: 1. Navigate to **Monitors** and select **+ New Monitor**. 2. Choose **Change Detection** as the monitor type. From here, you will configure the data source, query conditions, and alert thresholds. ## How Change Detection Works A change detection monitor compares two queries over time: 1. The monitor first runs a query for the current evaluation window (e.g. the last 15 minutes). 2. It then runs the same query offset by a chosen timeframe in the past (e.g. 1 hour ago). 3. The monitor computes the difference between the two query results. 4. If the difference exceeds the defined threshold, an alert notification is triggered. ## Change Types When configuring your monitor, you can specify how the change is measured: * **Change**: The raw difference between the current and past values. $$ a - b $$ * **% Change**: The percentage difference relative to the past value. $$ \frac{(a - b)}{b} \times 100 $$ ## Alert Conditions In the **Set Alert Conditions** step, you define the threshold for triggering an alert. The following operators are supported: * **Above** * **Below** * **Above or Equal** * **Below or Equal** An alert will be sent if the computed change meets the specified condition. Note: When monitoring for drops (using a **below** operator), the threshold value should usually be negative. For example, to alert on a 50% drop in volume, set the threshold to `-50` rather than `50`. This sends an alert notification when the percentage change falls below `-50%`, in other words, there has been a 50% drop. ## Configuration Options When creating a change detection monitor, you’ll need to configure the following: 1. **Source Dataset** – Select the dataset(s) on which the queries will be run. 2. **Filters** – (Optional) Narrow down results by applying filters. 3. **Aggregation Function** – Define how data points are aggregated (e.g. `count`, `average`, `max`, `sum`). 4. **Change Type** – Choose between **Change** or **% Change**. 5. **Evaluation Window** – The time period over which the aggregation is calculated (N minutes, hours, days, weeks, up to maximum of 1 month). 6. **Timeframe Offset** – How far back in time the comparison query should be run (N minutes, hours, days, weeks, up to maximum of 1 month ago). This example shows the following conditions: The **% change** for the **count** of events with **response\_status:200** over the past **1 hour** compared to **4 hours ago**. ## Example Use Cases * Detecting unusual traffic spikes compared to the same time yesterday. * Monitoring error rates that suddenly increase compared to the previous hour. * Tracking a drop in transaction volume relative to the past week. # Custom Parser Source: https://docs.bronto.io/core-features/custom-parser Generate custom log parsers automatically with LLMs to extract structured fields from Apache, IIS, HAProxy, Syslog, and custom log formats in Bronto. ## Overview Bronto's Custom Parser feature, powered by LLMs, enables you to automatically create custom log parsers for your specific data formats and requirements. Build, configure, and manage parsers that extract structured data from raw logs, transforming unstructured text into queryable, analyzable log events. Whether you're working with application logs, system logs, or custom formats, our custom parsing tool provides the flexibility to handle a diverse range of log data. ## Key Features ### Parser Creation and Configuration Create custom parsers with intuitive naming and description fields to help your team understand each parser's purpose and functionality. Define exactly what data you want to extract and how it should be structured. ### Real-Time Log Processing View raw log samples and see immediate parsing results as you configure your parser. Test your parsing logic against actual data before deploying to ensure accuracy and completeness. ### Structured Data Extraction Transform unstructured log data into structured, columnar formats with configurably defined fields. ### Multi-Format Support Out of the Box Built-in parsers for common log formats including: * **Apache HTTP Server logs** – Extract client IPs, authentication details, timestamps, HTTP request elements, response codes, and transfer sizes. * **Key-Value Pair logs** – Parse structured messages with field names, values, delimiters, and attribute groupings. * **Microsoft IIS logs** – Process IIS server logs with timestamps, client/server IPs, request details, and processing times. * **HAProxy logs** – Capture extended HAProxy data including client info, request/response details, timing metrics, and cookies. * **Linux Syslog** – Extract timestamps, hostnames, process names, PIDs, users, and log messages. ### Dataset Management Organize your parsing rules with dataset management: * Browse raw datasets and parsed results * Search and filter by dataset names * View data volumes and processing statistics * Track parser assignments and usage ### Performance Monitoring Monitor parser performance with detailed metrics: * Parse success rates * Processing volume over time * Parser efficiency analytics See our [Parser Metrics API endpoint](https://docs.bronto.io/api-reference/parsers/get-the-parsers-usage-metrics-over-a-period-of-time-for-a-log-id-1) for details. ## Technical Details Bronto uses **AWS Bedrock** as a managed service to access LLMs such as Claude. The infrastructure automatically selects the most appropriate model for each task and sends a structured prompt — for example, the AI log parser builds a prompt that instructs the model which patterns to avoid and how to handle keys such as timestamps. Model selection and prompt construction are handled automatically, so users can get started immediately without configuration. AWS Bedrock also provides the following security and compliance benefits relevant to a SaaS environment: * **Content safety** – Built-in safeguards to detect and filter harmful content * **Data privacy** – It never stores or uses our data to train models * **Network isolation** – All data remains within the AWS network * **Native integration** – Works seamlessly with Lambda, S3, and other AWS services, allowing AI capabilities to be incorporated without rearchitecting existing systems ## Getting Started 1. Navigate to the **Parsing** section from the main Bronto navigation menu. 2. Select **"Dataset List"** to view available parsers or create new ones. 3. Choose a dataset from your data sources. 4. Configure your parser with appropriate field mappings. 5. Test with sample data to verify parsing accuracy. Ensure the dataset includes a minimum of **100 events from the last 24 hours**. 6. Deploy and monitor your parser's performance. If you configure a custom parser, any dashboards, saved searches, or monitors that rely on specific key names in the log may stop working if those keys are renamed. # Log Forwarding Source: https://docs.bronto.io/core-features/log-forwarding Forward Bronto log events to an external Amazon S3 bucket for archiving, long-term storage, compliance workflows, or downstream processing. ## Overview Bronto supports outbound log forwarding so you can send log events outside of Bronto for archiving, long-term storage, compliance workflows, or downstream processing. Forwarding is configured through the Bronto API. A forward config defines the destination, the logs to forward, optional filters, compression, and batching limits. The currently supported destination type is Amazon S3. If S3 does not fit your needs, contact support to request integrations with other destinations. Common uses include: * Archiving selected log events to your own S3 bucket * Keeping an external copy of all current and future logs * Sending only matching events, such as warnings and errors, to a long-term store * Feeding downstream data processing or compliance review workflows ## How It Works A forward config can forward either all logs or a specific list of log IDs. When `all_logs` is set to `true`, Bronto forwards all logs in the account and automatically includes logs created in the future. When `all_logs` is set to `false`, provide the `log_ids` you want to forward. You can also add a `filter` to forward only matching events. Filters use Bronto search syntax, so you can target specific severities, services, environments, or any indexed event fields. Forwarded events are buffered and sent to S3 in payloads or batches. Depending on the volume of matching data and the batching configuration, it may take some time for enough events to be collected and uploaded. If data does not appear in S3 immediately after you create a forward config, wait for the next payload to be prepared and delivered. Before creating a forward config, allow Bronto to write to the target S3 bucket. Add a bucket policy like the following, replacing `` with the name of the bucket where you want to receive forwarded log data: ```json theme={"dark"} { "Version": "2012-10-17", "Statement": [ { "Sid": "Allow Bronto to write data to the S3 bucket", "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::637423326566:role/BrontoForwarder" ] }, "Action": "s3:*", "Resource": [ "arn:aws:s3:::", "arn:aws:s3:::/*" ] } ] } ``` After updating the bucket policy, use the test destination endpoint to confirm Bronto can write to the target S3 bucket. ## Configure Forwarding Use the API reference to create, test, update, retrieve, or delete forwarding configurations: * [Create a new forward config](/api-reference/forward/create-new-config) * [Test access to the destination](/api-reference/forward/test-access-to-destination) * [Retrieve forward configs](/api-reference/forward/retrieve-forward-configs) * [Update an existing forward config](/api-reference/forward/update-existing-config) * [Delete a forward config](/api-reference/forward/delete-a-config) ## Destination Options For S3 destinations, configure: * `bucket`: the target S3 bucket name * `prefix`: an optional key prefix, such as `bronto/archives/` * `storage_class`: the S3 storage class for forwarded objects Bronto supports `ZSTD`, `GZIP`, or no compression. `ZSTD` is recommended for reducing payload size. # Monitoring Overview & Threshold Monitors Source: https://docs.bronto.io/core-features/monitors Create threshold monitors in Bronto to evaluate logs or metrics on a schedule and alert teams via email, webhooks, Slack, or PagerDuty. ## Overview Bronto gives you the ability to create monitors that actively evaluate logs or metrics and notify your teams via email or custom webhooks. ## Create Monitors To create monitors in Bronto: Navigate to **Monitors** > **New Monitor**. Choose a data source. Select **Datasets** to monitor log search results, or **Metrics** to monitor an OpenTelemetry metric. Configure the query. For dataset monitors, select the dataset scope and apply a **filter** using Bronto's [search syntax](/query-syntax/search-syntax). For metric monitors, search for and select the metric you want to evaluate, then choose its aggregation function. Evaluate the query or formula over the desired time from the predefined options in **minutes**, **hours** or **days**. Set Alert Conditions. Configure monitors to trigger if the query or formula value crosses a threshold. Lastly, give the monitor a **name**, **description** , **email address** which can be an existing user or a custom email or select an existing webhook where the notification will be sent to. Edit Monitor Pn ## Add Queries and Formulas Use **+ Add Query** and **+ Add Formula** to build a monitor from more than one query result. Each query has a name, such as `errors`, `requests`, or `cpu`, which you can reference in a formula. If a monitor includes more than one query, add a formula to combine the query results before configuring the alert condition. ### Add a Query Select **+ Add Query** to add another independently configured query to the monitor. The new query can use a different data source, scope, filter, metric, aggregation, or grouping from the first query. For Sum, Summary, and Histogram metrics, select **Rate of sum** to evaluate the sum of metric values per second, or **Rate of count** to evaluate the number of observations or metric points per second. For details and examples, see [Aggregation functions](/metrics/explore-metrics#aggregation-functions). For example, to prepare a monitor that tracks the HTTP error rate: 1. Configure query `errors` to count requests with a status code of `500` or higher. 2. Select **+ Add Query**. 3. Configure query `requests` to count all requests. The monitor now has the failed request count in `errors` and the total request count in `requests`. ### Add a Formula Select **+ Add Formula** to calculate a value from numbers, query results, or a combination of both. Reference a query by entering its query name in the formula. Formulas support: * Parentheses: `(` and `)` * Addition, subtraction, multiplication, and division: `+`, `-`, `*`, and `/` * Numerical constants, including decimals, such as `100`, `5`, or `1.5` * Variables that match the names of queries in the monitor Variable names must be alphanumeric and start with a letter. Only variables based on query names in the monitor are allowed. You can reference any number of variables in a formula, and each monitor can include up to six queries. You can also use `+` and `-` as unary operators to explicitly set the sign of a value. For example, `errors + -5`, `-requests + 1000`, and `errors + +requests` are valid formulas. Continuing the HTTP error-rate example: 1. Select **+ Add Formula**. 2. Enter `errors / requests * 100` to calculate the percentage of requests that returned server errors. 3. Configure the alert condition against the formula result. For example, trigger the monitor when the error rate is above `5`. This alerts when more than 5% of requests return server errors. For metrics, formulas work the same way. For example, configure query `usage` as a CPU utilization metric and query `limit` as a CPU limit metric, then use `usage / limit * 100` to alert on percentage utilization. ## Setting Alert Conditions The alert conditions can be configured to trigger if the query or formula value reaches a predefined threshold. * Evaluate the query or formula over the last: *5 minutes*, *10 minutes*, *30 minutes*, *1 hour*, *2 hours*, *4 hours* or *1 day*. Evaluation is across a rolling time window in groups aligned from midnight. * Evaluate if query is *above*, *above or equal to*, *below*, or *below or equal* to the threshold. * Trigger if Alert Threshold literal value is matched. For metric monitors, threshold unit selection is a display helper. It lets you enter the threshold in a convenient unit and formats the preview chart, but it does not change the trigger logic. Bronto translates the selected unit into the raw value used to create and evaluate the monitor. Available aggregations depend on the query source and metric type. Metric monitors support the same aggregation functions as Metrics and Dashboards, including **Average**, **Count**, **Max**, **Min**, **Sum**, **Median**, **P25**, **P75**, **P90**, **P95**, **P99**, and **P999**, where supported by the selected metric type. Sum, Summary, and Histogram metrics also support **Rate of sum** and **Rate of count**. Rate functions are not available for Gauge metrics. The **Histogram** function and histogram views are not available in monitors; they are available in Dashboards and Metrics. ## Configure notifications Configure your notification messages to include the information you are most interested in and specify which user, email or webhook to send these alerts to. * Monitor Name. * Monitor Description. * View a preview of what the notification will look like. If you are sending monitor alerts to a webhook, see [Sample Payload Schema](/integrations/webhooks#sample-payload-schema) for the available variables and JSON template options. ## Manage Monitors Manage Monitors by editing, creating, bulk deleting and searching monitors all in the same place. From here you can easily view what email or webhook is associated to each monitor. Manage Monitors Pn ## View Monitor Details & Status Selecting a monitor to review from your list allows you to see its details which include its filter, source and recipients. From this page you can also view the status and event history Monitor Details Pn ## AI Investigation Reports When a monitor fires, Bronto can automatically run an investigation and deliver a detailed report. This helps responders move from alert to diagnosis faster by attaching AI-generated analysis directly to the monitoring workflow. Enable **AI Investigation Report** in the monitor configuration, then provide an **Investigation Prompt** to tell the AI what to check when the alert triggers. For the full workflow, prompt guidance, and feature details, see [AI Investigation Reports](/ai-features/ai-investigation-reports). # Patterns Source: https://docs.bronto.io/core-features/patterns Use Bronto Patterns to automatically group structurally similar log messages, search with precision, and analyze log frequency and volume. ## Overview Patterns automatically identify the common message structures in your log data as it is ingested. No configuration, schema definitions, or instrumentation changes are required. Log messages usually contain a static structure and dynamic values. For example, these events have the same structure even though their hostnames and retry counts differ: ```text theme={"dark"} Connection to db-1.prod failed after 3 retries Connection to db-2.prod failed after 7 retries ``` Bronto represents both events with a Pattern: ```text theme={"dark"} Connection to hostname: failed after num_retries: ``` Each unique Pattern receives a stable Pattern ID. When an ingested log event matches a Pattern, Bronto writes the Pattern ID to the event as an attribute before storing it. The ID remains unchanged for the retention period of the associated log data. Pattern IDs are first-class fields. You can use them to: * Filter searches to a specific message structure * Build logical query expressions * Group events and graph Pattern frequency over time * Identify the log statements generating the most volume * Create monitor filters that continue to target the intended log structure ## How Pattern Discovery Works Bronto automatically trains Patterns on up to the most recent **1 million events** in a dataset. If the dataset contains fewer events, Bronto trains on the events available. Training typically completes within a few minutes of data first arriving, but there is no guaranteed completion time. After training completes, new events that match a discovered Pattern are annotated with its Pattern ID during ingestion. Events ingested before Pattern training completes are not retroactively assigned a Pattern ID. Patterns that first appear after the training sample was collected may not be identified. A retraining mechanism may be added in the future to discover later message structures. ## Search and Analyze Patterns Patterns let you search by message structure instead of relying only on text shared by potentially unrelated log messages. For example, a text search for `timeout` might match several different code paths: ```text theme={"dark"} Request to payments timed out after 10s Lock acquisition timed out for key:checkout Client connection timed out:192.0.2.10 ``` With Patterns, you can select or query the specific message structure you want to investigate. Because the Pattern ID is stored as an event attribute, Pattern queries use Bronto's indexing and can be combined with other attributes. For example: ```sql theme={"dark"} ("$pattern_id" IN ('66fadcfb98d5c032', '4a465fe8dd5fbecd') AND response_code >= 500) OR ("$pattern_id" != '7c23016da7db413e' AND error IS NOT NULL) ``` See [Search Syntax](/query-syntax/search-syntax) for details about building queries. ### Group and Visualize Group by the Pattern ID to see the distinct message structures in a dataset and compare their frequency. This can help you: * Understand the normal behavior of an unfamiliar service * Identify Patterns that appear only during errors * Spot high-volume or noisy log statements * Track changes in log volume and investigate ingestion costs ## Use Patterns in Monitors You can use a Pattern ID in a monitor's filter to target a specific log structure. This avoids matching new, unrelated log messages that happen to contain the same words as the original event. For example, a text filter for `payment failed` could later match a recoverable `payment failed, retrying in 5s` message. A filter using the original Pattern ID continues to match only the selected message structure. See [Monitoring Overview & Threshold Monitors](/core-features/monitors) for information about creating monitor queries. There is currently no dedicated Pattern-based alerting workflow in the UI. Bronto does not yet provide alerts for a newly discovered Pattern or an anomalous change in a Pattern's frequency. ## Inferred Value Types Bronto attempts to infer the type of each dynamic value and replaces it with a corresponding placeholder. | Placeholder | Description | | - | - | | `<*>` | A wildcard used when a more specific type cannot be inferred, typically when a value can be a string or number | | `` | A UUID | | `` | A URL | | `` | A timestamp | | `` | A Boolean value | | `` | An IPv4 address | | `` | A semantic version, such as `4.7.12` | | `` | A number followed by a time unit, such as `10ms`, `2m`, or `5h` | | `` | A floating-point number | | `` | A value observed as both a float and an integer | | `` | An integer | | `` | A value from the event's hostname field | | `` | A default AWS EC2 hostname, such as `ip-123-123-123-123` | | `` | A string | ## Getting Started Patterns are enabled automatically for logs sent to Bronto. No changes to your logging configuration are required. 1. Send log data to a Bronto dataset. 2. Allow Pattern training to complete. This typically takes a few minutes after data first arrives. 3. Search or group by the `$pattern_id` event attribute. 4. Use a Pattern ID in queries, visualizations, or monitor filters like any other event field. Detected Patterns are also available through the `/patterns` API endpoint. # Service Level Objectives (SLOs) Source: https://docs.bronto.io/core-features/service-level-objectives Create trace-based service level objectives in Bronto using availability or latency indicators, targets, time windows, and notifications. Service Level Objectives (SLOs) turn request tracing data into measurable reliability targets for individual services and endpoints. In Bronto, you can measure availability or latency, set a target over a time window, and optionally send a notification when attainment reaches a threshold. ## SLO concepts | Term | Meaning | | - | - | | **Service Level Indicator (SLI)** | The measurement used to evaluate service behavior, such as the percentage of successful or sufficiently fast requests. | | **Service Level Objective (SLO)** | The target value an SLI should meet over a selected time window. | | **Attainment** | The percentage of valid requests that currently meet the objective. | | **Error budget** | The percentage of valid requests allowed to miss the objective. A 99% target provides a 1% error budget. | SLOs use request entry spans. Before creating one, make sure the service is sending traces with a `service.name`, endpoint information, request duration, and the status attributes needed to identify errors. See [Send Traces to Bronto](/tracing/send-traces). ## Find SLO candidates Select **SLOs** from the left navigation. Bronto analyzes request spans from the previous 28 days and suggests services and endpoints that may benefit from an objective. Each candidate summarizes its: * service and endpoint * success rate * p95 latency * request volume * recent error-rate or latency trend Use the service filter to narrow the list, or select **Rescan** to refresh the candidates. Select **Set an objective** beside a candidate to prefill its service and endpoint. To start without a candidate, select **New objective manually**. ## Create an objective Select a service and endpoint. Choose **Availability** or **Latency** as the SLI. Set the target percentage and select a rolling or calendar window. Name the objective and optionally configure a notification. Review the live preview and objective summary, then select **Create objective**. ### Choose an SLI Availability measures the share of valid requests that did not fail. Bronto evaluates one designated entry span per request. Select the service and endpoint, then define the **Error Indicator** that identifies a failed request. For example, `NOT ("http.response.status_code" < 500)` treats responses with a status code of `500` or greater as errors. Create an availability SLO by selecting a service, endpoint, error indicator, target, window, and notification Latency measures the share of valid requests completed faster than a threshold you set. Select the service and endpoint, then enter the **Latency Threshold** in milliseconds. Requests faster than this threshold count as good requests. Create a latency SLO by selecting a service, endpoint, latency threshold, target, window, and notification ### Set the target and window Enter the percentage of requests that must meet the SLI. For example, a target of `99%` requires 99 out of every 100 valid requests to be successful or faster than the selected threshold. Choose how Bronto evaluates the target: * **Rolling** continuously evaluates the most recent window. * **Calendar** evaluates the selected calendar-aligned window. Select the required window length from the available options, such as 7, 28, or 30 days. ### Configure notifications Give the objective a descriptive name. To receive an alert, enable **Notify me when attainment hits a threshold**, then select a configured notification channel and destination, such as a Slack channel. See [Slack notifications](/integrations/slack) for setup instructions. The **Live preview** and **Objective Summary** update as you configure the objective. Use them to confirm the scope, SLI, target, window, and notification settings before creating it. Nothing is saved until you select **Create objective**. After creation, the error budget can take up to two minutes to become available. # Bronto Ingestion Endpoints Source: https://docs.bronto.io/getting-started/bronto-endpoints Reference for Bronto's ingestion endpoints, including supported formats, OTLP and HTTP routes, regional URLs, authentication, and when to use each. ## Overview Bronto exposes two distinct endpoint types. Using the wrong one is the most common cause of `400` errors — confirm which applies to your agent before configuring. We recommend routing logs, metrics, and traces through the OpenTelemetry Collector rather than sending HTTP requests directly. The Collector handles batching, compression, and retries on failure. Log forwarders such as Fluent Bit, Logstash, and Vector remain a good choice for log-only sources. Direct HTTP is supported for cases where running an agent isn't practical. | Endpoint | Accepts | Typical clients | Where the signal appears | | - | - | - | - | | `ingestion.eu.bronto.io` / `ingestion.us.bronto.io` | Logs in JSON, syslog, logfmt, CEF, or raw text | Fluent Bit, Logstash, FireLens, EventBridge, custom HTTP | A dataset and collection in Log Search | | `ingestion.eu.bronto.io/v1/logs` / `ingestion.us.bronto.io/v1/logs` | OTLP protobuf or OTLP/JSON logs | OpenTelemetry Collector or SDK | A dataset and collection in Log Search | | `ingestion.eu.bronto.io/v1/metrics` / `ingestion.us.bronto.io/v1/metrics` | OTLP protobuf or OTLP/JSON metrics | OpenTelemetry Collector or SDK | [Metric Explorer](/metrics/explore-metrics); not a dataset or collection | | `ingestion.eu.bronto.io/v1/traces` / `ingestion.us.bronto.io/v1/traces` | OTLP protobuf or OTLP/JSON traces | OpenTelemetry Collector or SDK | [Explore Traces](/tracing/explore-traces); not a dataset or collection | ## Authentication All endpoints accept the Bronto API key header: ``` x-bronto-api-key: ``` The base ingestion endpoint also supports HTTP Basic authentication for products that provide a fixed authentication menu instead of custom headers: | Field | Value | | - | - | | Username | Any non-empty value, such as `bronto` | | Password | Your Bronto API key with the Ingestion role | ```bash Basic authentication theme={"dark"} curl -u "bronto:" \ -H "Content-Type: application/json" \ --data-binary '{"message":"authenticated with HTTP Basic"}' \ "https://ingestion..bronto.io/?service_namespace=&service_name=" ``` The username is ignored; the API key must be the password. Basic authentication applies to the base endpoint used for logs. Continue to use the `x-bronto-api-key` header for OTLP logs, metrics, and traces. See [API Keys](/Account-Management/API-Keys) for how to generate a key. *** ## Base Endpoint The base endpoint (no path) accepts any payload format and performs no schema validation. It is the right choice for any agent that sends JSON, plain text, or structured log lines over HTTP. ### Automatically parsed formats For the following formats, Bronto detects and extracts fields automatically — no configuration required. | Format | Fields extracted | | - | - | | **Structured JSON** (Logrus, Winston, etc.) | All top-level key-value fields | | **Nested JSON** | Nested objects flattened to dot notation — e.g. `context.user`, `context.request_id` | | **RFC 5424 Syslog** | `pri`, `facility`, `severity`, `hostname`, `appname`, `procid`, `msgid`, `timestamp`, `version` | | **Logfmt** | All key=value pairs — e.g. `level`, `msg`, `user`, `duration`. Also parsed when logfmt appears as the value of a JSON `message` field | | **GELF** | `version`, `host`, `short_message`, `level`, and underscore-prefixed custom fields | | **Log4j2 JSON** | `level`, `loggerName`, `message`, `thread`, `instant.epochSecond`, `instant.nanoOfSecond`, nested `thrown` fields | | **CEF** | CEF version and extension key-value pairs — e.g. `src`, `dst`, `suser` | ### Formats stored verbatim Other formats — RFC 3164 BSD syslog, Apache Common Log, Docker JSON, raw text — are accepted and stored as-is. Most log forwarders and the OpenTelemetry Collector can parse or transform these into structured fields before sending. If you are sending data directly, use the [custom parser](/core-features/custom-parser) to define extraction rules. *** ## OTLP Endpoints The `/v1/logs`, `/v1/metrics`, and `/v1/traces` endpoints accept OTLP over HTTPS on port `443` in **both protobuf and JSON encoding**. The OpenTelemetry Collector handles OTLP serialisation, batching, and retry automatically. | Signal | EU | US | | - | - | - | | Logs | `https://ingestion.eu.bronto.io/v1/logs` | `https://ingestion.us.bronto.io/v1/logs` | | Metrics | `https://ingestion.eu.bronto.io/v1/metrics` | `https://ingestion.us.bronto.io/v1/metrics` | | Traces | `https://ingestion.eu.bronto.io/v1/traces` | `https://ingestion.us.bronto.io/v1/traces` | Dataset and collection routing applies only to logs. Metrics and traces retain OpenTelemetry resource attributes such as `service.name`, but they do not create or appear in datasets or collections. Use the Metric Explorer for metrics and Explore Traces for traces. ### Encodings Set `Content-Type` to match the encoding you send. Protobuf remains the default for the Collector and the OTel SDKs, and is the more compact option on the wire. | Encoding | `Content-Type` | | - | - | | OTLP protobuf | `application/x-protobuf` | | OTLP/JSON | `application/json` | OTLP/JSON is useful when a client cannot produce protobuf — a script, a serverless function, or a platform that only emits JSON over HTTP. The body must be a single JSON object matching the OTLP request schema for that signal (for example `ExportLogsServiceRequest` for `/v1/logs`), not NDJSON. ```bash OTLP/JSON logs theme={"dark"} curl -X POST https://ingestion.eu.bronto.io/v1/logs \ -H "x-bronto-api-key: " \ -H "Content-Type: application/json" \ --data-binary '{ "resourceLogs": [{ "resource": { "attributes": [ {"key": "service.name", "value": {"stringValue": ""}}, {"key": "service.namespace", "value": {"stringValue": ""}} ] }, "scopeLogs": [{ "logRecords": [{ "timeUnixNano": "1705314600000000000", "severityText": "INFO", "body": {"stringValue": "user login successful"} }] }] }] }' ``` To send OTLP/JSON from an OpenTelemetry Collector, set `encoding: json` on the `otlphttp` exporter: ```yaml otel-config.yaml theme={"dark"} exporters: otlphttp: endpoint: https://ingestion.eu.bronto.io encoding: json headers: x-bronto-api-key: ``` OTel SDKs select the encoding through the exporter protocol — `http/protobuf` or `http/json`, set with `OTEL_EXPORTER_OTLP_PROTOCOL`. Not every language SDK implements `http/json`; check your SDK before switching. Bronto supports OTLP sums, gauges, summaries, and explicit histograms. Exponential histograms are not currently supported. You can calculate per-second rates for Sum, Summary, and Histogram metrics after ingestion; see [Aggregation functions](/metrics/explore-metrics#aggregation-functions). Trace data must go to `/v1/traces`. Sending traces to the base endpoint stores them as log events — trace correlation and the traces UI will not work. *** ## Direct HTTP Custom Ingestion If running a log forwarder or collector isn't practical, you can POST log events directly to the base endpoint from any HTTP client or script. ### Request format All requests must be `POST` with a JSON Lines (NDJSON) body — one JSON object per line. **Authentication** Authenticate with either the `x-bronto-api-key` header or HTTP Basic authentication as described above. Do not send the API key in a URL query parameter. **Required request header** | Header | Value | | - | - | | `Content-Type` | `application/json` | **Recommended headers** These headers control how log data is organized in Bronto. They do not route metrics or traces. See [Data Organization](/Search-and-Visualize/Partitions) for how log datasets, collections, and tags work. | Header | Description | | - | - | | `x-bronto-dataset` | Dataset to ingest into | | `x-bronto-collection` | Collection name | | `x-bronto-tags` | Comma-separated tags to attach to events | Products that support Basic authentication but cannot set routing headers can use `service_name` and `service_namespace` query parameters: ```text theme={"dark"} https://ingestion..bronto.io/?service_namespace=&service_name= ``` These parameters override `x-bronto-dataset` and `x-bronto-collection` when both forms are present. Parameters named `header_x-bronto-*` are not supported. **Other headers** | Header | Description | | - | - | | `Content-Encoding` | Compression format: `gzip`, `zstd`, or `deflate` | **Event fields** | Field | Required | Description | | - | - | - | | `message` | Yes | The log content string | | `timestamp` | Recommended | ISO 8601 timestamp — e.g. `2024-01-15T10:30:00Z` | ### Examples ```bash Uncompressed theme={"dark"} curl -X POST https://ingestion.eu.bronto.io \ -H "x-bronto-api-key: " \ -H "Content-Type: application/json" \ --data-binary '{"timestamp":"2024-01-15T10:30:00Z","message":"user login successful","user":"alice"} {"timestamp":"2024-01-15T10:30:01Z","message":"request completed","status":200}' ``` ```bash gzip theme={"dark"} echo '{"timestamp":"2024-01-15T10:30:00Z","message":"user login successful"}' | \ gzip | \ curl -X POST https://ingestion.eu.bronto.io \ -H "x-bronto-api-key: " \ -H "Content-Type: application/json" \ -H "Content-Encoding: gzip" \ --data-binary @- ``` ```bash Zstandard theme={"dark"} echo '{"timestamp":"2024-01-15T10:30:00Z","message":"user login successful"}' | \ zstd | \ curl -X POST https://ingestion.eu.bronto.io \ -H "x-bronto-api-key: " \ -H "Content-Type: application/json" \ -H "Content-Encoding: zstd" \ --data-binary @- ``` Zstandard offers the best compression ratio and is recommended for high-volume pipelines. ### Batch processing For large files, split into chunks and send each one: ```bash Batch ingest from file theme={"dark"} #!/bin/bash FILE="logs.ndjson" BATCH_SIZE=5000 API_KEY="" ENDPOINT="https://ingestion.eu.bronto.io" split -l $BATCH_SIZE "$FILE" /tmp/batch_ for batch in /tmp/batch_*; do gzip -c "$batch" | curl -s -X POST "$ENDPOINT" \ -H "x-bronto-api-key: $API_KEY" \ -H "Content-Type: application/json" \ -H "Content-Encoding: gzip" \ --data-binary @- echo "Sent $batch" done rm /tmp/batch_* ``` ### Compression ratios Compressing payloads before sending reduces transfer size significantly. Typical ratios for CDN logs: | Algorithm | `Content-Encoding` value | Typical ratio | | - | - | - | | gzip | `gzip` | \~7.8% | | Zstandard | `zstd` | \~6.0% | | Deflate | `deflate` | \~7.8% | ### Payload limits | Payload type | Maximum size | | - | - | | Uncompressed | 10 MB | | Compressed (wire size) | 10 MB | | Per line / entry | 256 KB (262,144 bytes) | Exceeding the payload size limits returns an HTTP `413`. ### Response codes | Code | Meaning | | - | - | | `200` | Events ingested | | `400` | Malformed request or invalid JSON | | `401` | Invalid or missing API key | | `413` | Payload exceeds size limit | | `429` | Rate limit or quota exhausted | A `200` response means your data has been securely stored — no data will be lost. If the API returns an error, no data from that request is ingested. # Custom Log Ingestion Source: https://docs.bronto.io/getting-started/custom-ingestion Send log events directly to Bronto via HTTP using the Ingestion API — with full control over compression, batching, metadata, and authentication. The Bronto Ingestion API lets you POST log events directly to Bronto from any HTTP client or script. This is useful when you need to build a custom pipeline, integrate with an existing system, or ingest logs programmatically without an agent. ## Prerequisites You'll need an API key with ingestion or admin permissions. See [API Keys](/Account-Management/API-Keys) for how to create one. ## Endpoints * `https://ingestion.eu.bronto.io` — EU region * `https://ingestion.us.bronto.io` — US region OTLP logs can also be sent to `https://ingestion.eu.brontobytes.io/v1/logs` or `https://ingestion.us.brontobytes.io/v1/logs`. ## Request Format All requests must be `POST` with a JSON Lines (NDJSON) body — one JSON object per line. ### Required headers | Header | Value | | - | - | | `x-bronto-api-key` | Your Bronto API key | | `Content-Type` | `application/json` | ### Recommended headers These headers control how log data is organized in Bronto. See [Data Organization](/Search-and-Visualize/Partitions) for how log datasets, collections, and tags work. | Header | Description | | - | - | | `x-bronto-dataset` | Dataset to ingest into | | `x-bronto-collection` | Collection name | | `x-bronto-tags` | Comma-separated tags to attach to events | ### Other headers | Header | Description | | - | - | | `Content-Encoding` | Compression format: `gzip`, `zstd`, or `deflate` | ### Event schema Each line in the request body should be a JSON object with the following fields: | Field | Required | Description | | - | - | - | | `message` | Yes | The log content string | | `timestamp` | Recommended | ISO 8601 timestamp (e.g. `2024-01-15T10:30:00Z`) | ## Send logs ### Uncompressed ```bash Send logs theme={"dark"} curl -X POST https://ingestion.eu.bronto.io \ -H "x-bronto-api-key: " \ -H "Content-Type: application/json" \ --data-binary '{"timestamp":"2024-01-15T10:30:00Z","message":"user login successful","user":"alice"} {"timestamp":"2024-01-15T10:30:01Z","message":"request completed","status":200}' ``` ### With gzip compression ```bash Send logs with gzip theme={"dark"} echo '{"timestamp":"2024-01-15T10:30:00Z","message":"user login successful"}' | \ gzip | \ curl -X POST https://ingestion.eu.bronto.io \ -H "x-bronto-api-key: " \ -H "Content-Type: application/json" \ -H "Content-Encoding: gzip" \ --data-binary @- ``` ### With Zstandard compression ```bash Send logs with zstd theme={"dark"} echo '{"timestamp":"2024-01-15T10:30:00Z","message":"user login successful"}' | \ zstd | \ curl -X POST https://ingestion.eu.bronto.io \ -H "x-bronto-api-key: " \ -H "Content-Type: application/json" \ -H "Content-Encoding: zstd" \ --data-binary @- ``` ### With deflate compression ```bash Send logs with deflate theme={"dark"} echo '{"timestamp":"2024-01-15T10:30:00Z","message":"user login successful"}' | \ python3 -c "import sys,zlib; sys.stdout.buffer.write(zlib.compress(sys.stdin.buffer.read()))" | \ curl -X POST https://ingestion.eu.bronto.io \ -H "x-bronto-api-key: " \ -H "Content-Type: application/json" \ -H "Content-Encoding: deflate" \ --data-binary @- ``` ## Batch processing For large files, use a shell script to split the file into chunks and send each one: ```bash Batch ingest from file theme={"dark"} #!/bin/bash FILE="logs.ndjson" BATCH_SIZE=5000 API_KEY="" ENDPOINT="https://ingestion.eu.bronto.io" split -l $BATCH_SIZE "$FILE" /tmp/batch_ for batch in /tmp/batch_*; do gzip -c "$batch" | curl -s -X POST "$ENDPOINT" \ -H "x-bronto-api-key: $API_KEY" \ -H "Content-Type: application/json" \ -H "Content-Encoding: gzip" \ --data-binary @- echo "Sent $batch" done rm /tmp/batch_* ``` ## Compression ratios Compressing payloads before sending reduces transfer size significantly. Typical compression ratios for CDN logs: | Algorithm | `Content-Encoding` value | Typical ratio | | - | - | - | | gzip | `gzip` | \~7.8% | | Zstandard | `zstd` | \~6.0% | | Deflate | `deflate` | \~7.8% | Zstandard offers the best compression ratio and is recommended for high-volume pipelines. ## Payload size limits | Payload type | Maximum size | | - | - | | Uncompressed | 10 MB (10,485,760 bytes) | | Compressed (wire size) | 10 MB (10,485,760 bytes) | Exceeding these limits returns an HTTP `413` response. ## Response codes | Code | Meaning | | - | - | | `200` | Success — events ingested | | `400` | Malformed request or invalid JSON | | `401` | Invalid or missing API key | | `413` | Payload exceeds size limit | | `429` | Rate limit or quota exhausted | | `500` | Server error | ## Reliable delivery A `200` response means your data has been securely stored and will be ingested — no data will be lost. If the API returns an error response, no data from that request will be ingested. Bronto is built for reliable, end-to-end delivery. Once you receive a `200`, your logs are safe. # Glossary Source: https://docs.bronto.io/getting-started/glossary Definitions for Bronto-specific terms used across the documentation, including datasets, collections, partitions, monitors, and ingestion concepts. This glossary defines the Bronto-specific terms used across the docs. Use this page as the source of truth for product terminology. If a page uses a term differently, update that page to match the definitions below. ## A ### Agent An **[agent](/agent-setup/agent-intro)** is software you run or configure to send log data into Bronto from hosts, services, or platforms. ### API Key An **[API key](/Account-Management/API-Keys)** is a credential used to authenticate programmatic access to Bronto APIs and integrations such as [Local MCP](/ai-features/local-mcp). ## B ### BrontoScope **[BrontoScope](/ai-features/brontoscope)** is Bronto’s AI investigation feature. It analyzes an error event, identifies likely causes and impact, and returns recommended next steps with supporting evidence. ## C ### Collection A **[collection](/Search-and-Visualize/Partitions)** is a logical grouping of log datasets. Use collections to organize related log datasets and to separate datasets that may share the same name in different environments. Metrics and traces do not belong to collections. ### Custom Parser **[Custom Parser](/core-features/custom-parser)** is Bronto’s LLM-assisted parsing feature. It converts raw, unstructured logs into structured, queryable events. ## D ### Dashboard A **[dashboard](/Search-and-Visualize/Dashboards)** is a saved visual view of query results used to monitor systems, services, or trends over time. ### Dataset A **[dataset](/Search-and-Visualize/Partitions)** is Bronto’s fundamental unit of log storage. It contains log events that share a similar origin or format and is always queried as a unit. Metrics and traces are stored separately and appear in the [Metric Explorer](/metrics/explore-metrics) and [Explore Traces](/tracing/explore-traces), not in datasets. ## E ### Event An **[event](/Search-and-Visualize/Log-Search)** is a single log record stored in Bronto. ## H ### Hosted MCP **[Hosted MCP](/ai-features/hosted-mcp)** is Bronto’s managed MCP server. It lets supported AI clients connect to Bronto over Bronto-hosted infrastructure using Bronto authentication. ## I ### Ingestion **[Ingestion](/getting-started/quick-ingestion)** is the process of sending log data into Bronto. ## L ### Local MCP **[Local MCP](/ai-features/local-mcp)** is Bronto’s self-hosted MCP server. You run it locally and connect AI agents to Bronto using your API key and regional API endpoint. ### Log Search **[Log Search](/Search-and-Visualize/Log-Search)** is Bronto’s main search experience for exploring events, filtering data, and running queries across large volumes of logs. ## M ### MCP **[MCP](/ai-features/hosted-mcp)** stands for **Model Context Protocol**. In Bronto, it refers to the protocol used to let AI tools access Bronto data and search capabilities through [Hosted MCP](/ai-features/hosted-mcp) or [Local MCP](/ai-features/local-mcp). ### My Data **[My Data](/My-Data/My-Data)** is the Bronto page for managing collections and datasets, reviewing parser coverage and data quality, and understanding ingestion and search usage across your account. ### Monitor A **[monitor](/core-features/monitors)** is an automated rule that evaluates a query or condition and triggers an alert when that condition is met. ## N ### Notification Channel A **notification channel** is the destination used for [monitor](/core-features/monitors) alerts, such as [Slack](/integrations/slack) or a [webhook](/integrations/webhooks). ## O ### Organization An **[organization](/Account-Management/Multi-Org)** is the top-level Bronto account boundary for users, settings, datasets, access controls, and billing or usage. ## P ### Partition Tag A **[partition tag](/Search-and-Visualize/Partitions)** is a special organization-level tag used to control how incoming data is grouped into collections and datasets. Partition tags should be stable, low-cardinality attributes such as environment, region, or service. ## Q ### Query A **[query](/query-syntax/search-syntax)** is an instruction used in Bronto to search, filter, aggregate, or analyze log data. ## S ### Saved Search A **[saved search](/Search-and-Visualize/Saved-Searches)** preserves a query and its related view settings — including column selection and ordering — for reuse. ### Search **[Search](/Search-and-Visualize/Log-Search)** is the act of querying log data in Bronto to find events, patterns, or trends. ### SSO **[SSO](/Account-Management/SSO/SSO-Overview)** stands for **single sign-on**. In Bronto, it refers to centralized authentication through an identity provider. ## T ### Tag A **tag** is a key-value label assigned to a [dataset](/Search-and-Visualize/Partitions). Tags help categorize datasets and make them easier to find, group, and query. ### Threshold Monitor A **[threshold monitor](/core-features/monitors)** is a monitor that alerts when a query result crosses a defined value. ### Trace A **[trace](/tracing/explore-traces)** is the end-to-end record of a request as it moves through services, captured as a set of spans. [Send traces](/tracing/send-traces) to Bronto using OpenTelemetry, then [explore](/tracing/explore-traces) them to investigate latency, errors, and service dependencies. # Try Bronto with the OpenTelemetry Demo Source: https://docs.bronto.io/getting-started/otel-demo Run the OpenTelemetry Demo (Astronomy Shop) locally and route its logs, metrics, and traces to Bronto to explore real, correlated telemetry. The [OpenTelemetry Demo](https://opentelemetry.io/docs/demo/) — the "Astronomy Shop" — is a microservices application maintained by the OpenTelemetry project. It runs around 20 services written in different languages, emits logs, traces, and metrics, and ships a built-in load generator that keeps realistic traffic flowing. It's the fastest way to see what Bronto looks like with real, correlated data when you don't yet have your own application instrumented. Because every service in the demo already exports to a bundled **OpenTelemetry Collector**, "trying Bronto" mostly means adding a Bronto exporter to a configuration you don't have to write yourself. ## What you'll see Once data is flowing, Bronto will show: * **Traces** spanning the full checkout flow across services (frontend → cart → checkout → payment → shipping, and more). * **Logs** automatically correlated to those traces via `trace_id`, so you can jump from a log line to the request that produced it. * **Metrics** for request volume, latency, runtime behavior, and service health in the Metric Explorer. * A `service.name` per microservice, used to filter metrics and traces and mapped to a Bronto Dataset for logs only. Metrics and traces do not appear in datasets or collections. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, use **Rate of sum** or **Rate of count** in the Metric Explorer to visualize per-second rates. ## Prerequisites * A Bronto API key — see [API Keys](/Account-Management/API-Keys) to create one. * Your Bronto region (`eu` or `us`). The examples below use the EU endpoints; swap in `us` if that's your region. See [Ingestion Endpoints](/getting-started/bronto-endpoints). * Either **Docker** (with Docker Compose) or a **Kubernetes** cluster with **Helm**. ## Step 1 — Get the demo ```bash Docker Compose theme={"dark"} git clone https://github.com/open-telemetry/opentelemetry-demo.git cd opentelemetry-demo ``` ```bash Helm theme={"dark"} helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts helm repo update ``` ## Step 2 — Add Bronto as an exporter The demo's Collector is designed to be extended. Add a Bronto `otlphttp` exporter and append it to the existing **logs**, **metrics**, and **traces** pipelines. The OpenTelemetry Collector merges config files but **replaces** lists rather than appending to them. When you redefine a pipeline's `exporters`, you must repeat the demo's upstream exporters so they keep working alongside Bronto. The demo provides a dedicated, normally-empty extension file for exactly this purpose. Edit `src/otel-collector/otelcol-config-extras.yml`: ```yaml src/otel-collector/otelcol-config-extras.yml theme={"dark"} exporters: otlphttp/bronto: logs_endpoint: https://ingestion.eu.bronto.io/v1/logs metrics_endpoint: https://ingestion.eu.bronto.io/v1/metrics traces_endpoint: https://ingestion.eu.bronto.io/v1/traces compression: none headers: x-bronto-api-key: service: pipelines: traces: # repeat the upstream exporters, then add Bronto exporters: [otlp_grpc/jaeger, debug, span_metrics, otlphttp/bronto] logs: exporters: [opensearch, debug, otlphttp/bronto] metrics: # repeat the current upstream exporters, then add Bronto exporters: [otlphttp/prometheus, debug, otlphttp/bronto] ``` Replace `` with your key and adjust the region in both endpoints if you're on US. The upstream exporter names above (`otlp_grpc/jaeger`, `span_metrics`, `opensearch`, …) are listed in the comments at the top of `otelcol-config-extras.yml`. If a future version of the demo changes them, copy the current names from that file so you don't drop the demo's own backends. Override the bundled Collector config through the chart's values. Create `bronto-values.yaml`: ```yaml bronto-values.yaml theme={"dark"} opentelemetry-collector: config: exporters: otlphttp/bronto: logs_endpoint: https://ingestion.eu.bronto.io/v1/logs metrics_endpoint: https://ingestion.eu.bronto.io/v1/metrics traces_endpoint: https://ingestion.eu.bronto.io/v1/traces compression: none headers: x-bronto-api-key: service: pipelines: traces: # repeat the upstream exporters, then add Bronto exporters: [otlp, debug, spanmetrics, otlphttp/bronto] logs: exporters: [opensearch, debug, otlphttp/bronto] metrics: # repeat the chart's current upstream exporters, then add Bronto exporters: [otlphttp/prometheus, debug, otlphttp/bronto] ``` The same list-replace rule applies: include the chart's existing exporters for each pipeline. Inspect the rendered defaults with `helm show values open-telemetry/opentelemetry-demo` if you're unsure of the current names. Avoid committing your API key. Reference a Kubernetes Secret instead, or pass the key with `--set 'opentelemetry-collector.config.exporters.otlphttp/bronto.headers.x-bronto-api-key='` at install time. ## Step 3 — Start the demo ```bash theme={"dark"} docker compose up --force-recreate --remove-orphans --detach ``` The web store is available at [http://localhost:8080](http://localhost:8080). The built-in load generator starts producing traffic automatically, so telemetry begins flowing without any manual clicks. ```bash theme={"dark"} helm install my-otel-demo open-telemetry/opentelemetry-demo --values bronto-values.yaml ``` Follow the chart's output notes to port-forward the frontend proxy. The load generator runs in-cluster and starts traffic on its own. ## Step 4 — Explore your data in Bronto Within a minute or two, telemetry should appear in Bronto. Here are two quick things to try. Open [Explore Traces](/tracing/explore-traces) and pick a recent trace from the `frontend` service. Expand the spans to watch a single checkout request fan out across cart, currency, payment, and shipping. Click a span's `trace_id` to pivot into the correlated logs for that exact request. Bronto trace explorer showing operations from the OpenTelemetry Demo Bronto trace waterfall for a single request from the OpenTelemetry Demo Open the Metric Explorer and select a metric emitted by the demo. Filter by `service.name` to compare services, then use the result in a [dashboard](/Search-and-Visualize/Dashboards). Connect the [Bronto MCP server](/ai-features/hosted-mcp) to your AI assistant and query the demo data in plain language — no query syntax required. Ask for an error summary, a latency outlier, or which service is failing, and let the assistant investigate across the demo's logs and traces. Claude using the Bronto MCP server to summarize errors from the OpenTelemetry Demo Want to generate errors on demand? The demo includes a feature-flag service that can inject failures (such as a failing payment or cart service). Toggling those flags is a good way to see how problems surface in Bronto's traces and logs. ## Troubleshooting If data doesn't appear: * Confirm the endpoints match your region (`eu` vs `us`) and end in `/v1/logs`, `/v1/metrics`, and `/v1/traces`. * Confirm the `x-bronto-api-key` header is present and the key is valid. * Confirm you repeated the demo's existing exporters in each pipeline — a typo there can silently drop the whole pipeline. * Check the Collector logs (`docker compose logs otel-collector`, or the collector pod) for export errors. ## Next steps Once the demo makes sense, point your own application's OTLP traces at Bronto. Use the language guides to add OpenTelemetry logs, metrics, and traces to your services. # Quick Ingest Source: https://docs.bronto.io/getting-started/quick-ingestion Send data directly to Bronto in seconds using an API key with no agent or forwarder configuration required, ideal for testing or one-off ingestion. Skip the agent setup and get your data into Bronto instantly. Quick Ingest gives you a guided configure page and ready-made request snippets for sending events directly to Bronto — ideal for testing, one-off ingestion, or getting up and running fast. For production environments or continuous log forwarding, see the [Agent Setup](/agent-setup/agent-intro) guide. ## Send Data To start quick ingestion, open **My Data** from the application sidebar, then click **Add Data**. Bronto opens the onboarding configure page, where you can choose how you want to send data and test that events are arriving. From the application sidebar, select **My Data**. Click **Add Data** in the top-right of the page, which opens the onboarding configure page. Use one of the configure page options: **Have a telemetry agent config already?**, **Setting up with an LLM or agent?**, or **Set up with docs**. You can also select an integration from the docs panel or click **View All** to browse the full list. Click **Generate API Key** to create an ingestion key from the configure page, or use an existing [API key](/Account-Management/API-Keys) with ingestion permissions. Click **Test Connection** to open a ready-made request snippet. Choose **cURL**, **HTTP**, or **Python**, add your API key, then run the snippet to send a sample event. ## Verify Ingestion Use **Test Connection** on the onboarding configure page to send a sample event and confirm that Bronto can receive data with your API key. The Test Connection modal includes: * A language selector for **cURL**, **HTTP**, and **Python** snippets * **Generate API Key** for creating an ingestion key without leaving the flow * **Copy Snippet** for copying the generated request * **Go to my logs** for opening Log Search after sending the sample event After you run the snippet, wait for the "Waiting for events" status on the configure page to update, or click **Go to my logs** to inspect the ingested event directly. # Ingest Data into Bronto Source: https://docs.bronto.io/ingest-data/overview Choose how to get your logs, metrics, and traces into Bronto — agents, cloud providers, CDNs, applications, infrastructure, databases, and OpenTelemetry. ## Overview Bronto ingests logs, metrics, and traces from almost any source. Pick the section below that matches where your data lives — each one walks through the available methods and the configuration steps to get data flowing. Each signal has its own destination in Bronto: | Signal | Where to view it | Dataset and collection behavior | | - | - | - | | Logs | [Log Search](https://app.bronto.io/search) | Stored in a dataset and collection | | Metrics | [Metric Explorer](/metrics/explore-metrics) | Not stored in a dataset or collection | | Traces | [Explore Traces](/tracing/explore-traces) | Not stored in a dataset or collection | New to Bronto? Start with the [Quick Ingestion](/getting-started/quick-ingestion) guide for the fastest path to sending your first events, and keep the [Bronto Endpoints](/getting-started/bronto-endpoints) reference handy for the URLs and ports each method uses. ## Choose a data source Collect from your hosts with OpenTelemetry, Fluent Bit, Fluentd, Logstash, the Datadog Agent, or Vector. Send logs, traces, and metrics from AWS services using S3, CloudWatch, Firehose, EventBridge, FireLens, and ADOT. Stream telemetry from Azure services, VMs, and OpenTelemetry-instrumented workloads. Forward edge and access logs from Akamai, Cloudflare, and Fastly. Capture events from Auth0, Okta, GCP, Heroku, PagerDuty, Vercel, and more. Collect from Kubernetes, Docker, proxies, message queues, identity providers, and databases like PostgreSQL, MySQL, MongoDB, and Redis. Instrument your applications with the OpenTelemetry SDK across Python, Java, Go, .NET, Node.js, and more. Capture distributed traces and RED metrics with no code changes, no SDK, and no redeploy, using OpenTelemetry eBPF Instrumentation (OBI). # Akamai Source: https://docs.bronto.io/integrations/akamai Stream Akamai CDN logs to Bronto with DataStream 2 for real-time visibility into edge traffic, errors, cache performance, and security events. ## Overview Akamai Datastream2 enables streaming CDN logs to third-party solutions via [HTTPS endpoints](https://techdocs.akamai.com/datastream2/docs/stream-custom-https). This guide walks you through configuring a Datastream2 *destination* to send logs to Bronto. For the rest of the stream configuration, such as selecting which fields to be included in the log data, please refer to the [Akamai documentation](https://techdocs.akamai.com/datastream2/docs/welcome-datastream2). ### Destination Configuration To configure a Datastream2 stream for Bronto: 1. Prepare your Bronto destination details: * Collection (service\_namespace) * Dataset (service\_name) * Ingestion API key. See the [Bronto API Keys documentation page](/Account-Management/API-Keys) for details. 2. Use the following URL format for your destination: ```url theme={"dark"} https://ingestion.eu.bronto.io/?service_name=MyBrontoDataset&service_namespace=MyBrontoCollection ``` 3. In the Datastream2 configuration simply: * Set Authentication to `None` * Enable compression * Add a custom header: * Name: `x-bronto-api-key` * Value: Your Bronto Ingestion API key ### Configuration Screenshots # Send Auth0 events to Bronto Source: https://docs.bronto.io/integrations/auth0 Stream Auth0 authentication and user lifecycle events — logins, MFA challenges, and password resets — to Bronto with Auth0 Event Streams. ## Overview Auth0 emits events for every login, logout, user creation, password reset, MFA challenge, and organization change. This guide connects those events to Bronto using Auth0 Event Streams. ## Prerequisites * A Bronto account and API key. See [API Keys](/Account-Management/API-Keys). * Admin access to your Auth0 tenant * Auth0 Free plan or above. Event Streams is available on all plans. ## Configure the Event Stream In your Auth0 dashboard, navigate to **Monitoring → Event Streams** and click **+ Create Event Stream**. From the list of stream types, select **Webhook**. Fill in the following values: **Stream Name** ``` Bronto ``` **Endpoint** For EU: ``` https://ingestion.eu.bronto.io/?service_name=Auth0&service_namespace= ``` For US: ``` https://ingestion.us.bronto.io/?service_name=Auth0&service_namespace= ``` **Authentication Method** ``` Custom Header ``` **Header Key** ``` x-bronto-api-key ``` **Header Value** ``` ``` Choose the Auth0 event categories you want to forward. To capture all authentication activity, enable **Select all events** under each category, or pick specific ones such as: * `user.created` * `user.updated` * `organization.connection.added` * login and logout events Click **Save**. The stream status should show **Enabled**. For full details on Auth0 Event Streams, see the [Auth0 Event Streams documentation](https://auth0.com/docs/customize/events/create-an-event-stream). ## Verify in Bronto Open Bronto and go to [Search](https://app.bronto.io/search). Trigger a test event, for example by logging in to your Auth0-connected application or creating a test user, and confirm the event appears in the UI. ## What you will see in Bronto Auth0 events arrive in CloudEvents format with: * a top-level `type` field such as `organization.connection.updated` * a `source` field identifying the Auth0 tenant * a `data` object containing the event payload Useful fields to filter on include: * `type` * `data.context.tenant.id` * `data.object` ## Troubleshooting * **No events appearing?** Check that the Event Stream shows as **Enabled** in Auth0 and confirm the endpoint URL and API key are correct. * **Getting 401 errors?** Verify the `x-bronto-api-key` header value matches a valid Bronto API key with the Ingestion role. * **Events landing without a dataset or collection?** Confirm the `service_name` and `service_namespace` query parameters are present and correctly spelled in the endpoint URL. # AWS S3 Access Log Source: https://docs.bronto.io/integrations/aws Set up the AWS S3 access log integration in Bronto to ingest server access logs from S3 buckets and analyze object access, requests, and errors. ### Overview Please note this In-App option is for S3 Access Log ingestion only, for all other use cases refer to our Client Side option. To set up the AWS integration manually, create an IAM policy and IAM role in your AWS account, and configure the role with an AWS External ID generated in your Bronto account. This allows Bronto’s AWS account to query AWS APIs on your behalf, and pull data into your Bronto account. The sections below detail the steps for creating each of these components, and then completing the setup in your Bronto account. ### Setup In the [AWS integration configuration page](https://app.eu.bronto.io/integrations/aws-cloud), click the “Add New AWS Account” button. Enter your AWS account ID in the “AWS Account ID” field and click "Generate External ID". The ID will be generated and available for you to copy. For more information on AWS External IDs\*\*, \*\*see the [IAM user guide](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html). Create a new role in the AWS [IAM Console](https://console.aws.amazon.com/iam/home#/roles). Select **Custom trust policy** for the trusted entity type and paste the trust policy below. (**Note:** don’t forget to copy in your External ID generated on the [integration page](https://app.eu.bronto.io/integrations/aws-cloud)) Skip the permission policy section as it will be created after the role. Name the role `BrontoBytesIntegration-AWSRole`, and provide an apt description. Click **Create Role**. Create an IAM policy for the BrontoBytes role in your AWS account with the necessary permissions to take advantage of every AWS integration offered by BrontoBytes. As other components are added to an integration, these permissions may change. Go to the newly created `BrontoBytesIntegration-AWSRole` role in the [AWS IAM Console](https://console.aws.amazon.com/iam/home#/roles). Click `Add Permissions` and choose `Create inline policy`. Paste the **BrontoBytes Integration Policy** below. Click **Next** to review your changes. Name the policy `BrontoBytesIntegrationPolicy` or one of your own choosing, and provide an apt description. Click **Create policy**. AWS IAM permissions enable Bronto to collect metrics, tags, EventBridge events, and other data necessary to monitor your AWS environment. To correctly set up the AWS Integration, you must attach the relevant IAM policies to the Bronto AWS Integration IAM Role in your AWS account. ### AWS Integration IAM Custom Trust Policy Don’t forget to copy in your External ID generated on the integration page ```json theme={"dark"} { "Version": "2012-10-17", "Statement": [ { "Sid": "BrontoBytesAssumeRole", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::637423326566:role/BrontoBytesAWSIntegration" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "" } } } ] } ``` ### Bronto Integration Policy The below config needs to be updated first before pasting. *BUCKET\_NAME*is the name of the S3 bucket that contains the log data and *PREFIX* is the path to the parent folder where the logs are actually stored. ```json theme={"dark"} { "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:List*", "s3:Get*" ], "Effect": "Allow", "Resource": [ "arn:aws:s3::://*", "arn:aws:s3:::" ] } ] } ``` ### S3 Notifications The final step is to enable notifications for your S3 bucket. This will allow Bronto to receive notifications when new objects are added to your bucket. Go to the [S3 console](https://console.aws.amazon.com/s3/home) and find the bucket you want to enable notifications for. Choose the `Properties` tab and scroll down to `Event notifications` Click **Create event notification** Set the event type to `All object create events` Set the destination to `SNS Topic` and enter ARN that matches the region where your bucket is: * ****EU West 1**** ``` arn:aws:sns:eu-west-1:637423326566:brontobytes-aws-ingestion ``` * ****US East 1**** ``` arn:aws:sns:us-east-1:637423326566:brontobytes-aws-ingestion ``` # AWS Distribution for OpenTelemetry (ADOT) Source: https://docs.bronto.io/integrations/aws-adot Send application logs, metrics, and traces from Amazon ECS, EKS, or EC2 to Bronto with AWS Distro for OpenTelemetry (ADOT), avoiding CloudWatch fees. ## When to Use ADOT ADOT is a good fit when you are running containerised workloads on ECS or EKS and want to: * Send application **logs, metrics, and traces** to Bronto through one Collector * Avoid CloudWatch log ingestion fees entirely * Use an AWS-supported, pre-built distribution of the OpenTelemetry Collector without managing it yourself If you need full control over collector configuration — custom processors, fan-out to multiple backends, or advanced transformation — consider the [Self-Managed OTel Collector](./aws-custom-otel) instead. *** ## Supported AWS Services ADOT collects application logs, metrics, and traces from containerised workloads on: | Service | Data types | | - | - | | Amazon ECS (EC2 launch type) | Application logs, metrics, and traces (sidecar) | | AWS Fargate (ECS) | Application logs, metrics, and traces (sidecar) | | Amazon EKS (EC2 node groups) | Application logs, metrics, and traces (DaemonSet) | | Amazon EKS (Fargate) | Application logs, metrics, and traces (sidecar) | For Lambda traces, use the [ADOT Lambda Layer](./aws-adot-lambda). For non-containerised AWS services, see the [overview](./aws-overview). ADOT forwards the telemetry your workload sends it — it does not automatically discover application telemetry. Instrument your app with the [OpenTelemetry SDK](/opentelemetry/overview) so it exports logs, metrics, and traces to the ADOT sidecar or DaemonSet. *** ## What is ADOT? The [AWS Distribution for OpenTelemetry](https://aws-otel.github.io/) (ADOT) is an AWS-supported build of the OpenTelemetry Collector. It is available as a Docker image and can be deployed as a sidecar container (ECS) or a daemonset (EKS). It collects logs, metrics, and traces from your application via OTLP and forwards them to any OTLP-compatible backend — including Bronto. ADOT itself is free. You pay only for the compute running the container. *** ## Bronto Ingestion Endpoints | Signal | EU Region | US Region | | - | - | - | | Logs | `https://ingestion.eu.bronto.io/v1/logs` | `https://ingestion.us.bronto.io/v1/logs` | | Metrics | `https://ingestion.eu.bronto.io/v1/metrics` | `https://ingestion.us.bronto.io/v1/metrics` | | Traces | `https://ingestion.eu.bronto.io/v1/traces` | `https://ingestion.us.bronto.io/v1/traces` | The `/v1/logs`, `/v1/metrics`, and `/v1/traces` endpoints accept **OTLP protobuf only**. All requests require the header: ``` x-bronto-api-key: ``` See [API Keys](/Account-Management/API-Keys) for how to generate a key. *** ## Setup on ECS (Sidecar) Add the ADOT container as a sidecar to your ECS task definition. The typical local defaults are `localhost:4317` for OTLP/gRPC and `localhost:4318` for OTLP/HTTP. Use the receiver address, protocol, and TLS settings configured for your task when they differ; the sidecar then forwards the telemetry to Bronto. ### ADOT Collector Configuration Create a collector config file and make it available to the container (via S3, SSM Parameter Store, or a custom image). ```yaml theme={"dark"} receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: exporters: otlphttp/bronto: logs_endpoint: "https://ingestion..bronto.io/v1/logs" metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" traces_endpoint: "https://ingestion..bronto.io/v1/traces" compression: none headers: x-bronto-api-key: ${env:BRONTO_API_KEY} service: pipelines: logs: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] metrics: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] traces: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] ``` Replace `` with `eu` or `us`. In production, do not bake the API key into the YAML. Inject it into the container from AWS Secrets Manager as `BRONTO_API_KEY`, then use `${env:BRONTO_API_KEY}` as the header value. ADOT also accepts the complete configuration through `AOT_CONFIG_CONTENT`, which can be populated from a protected SSM parameter at deployment time. ADOT does not include every upstream Collector component. In particular, its standard image does not include the `transform` processor. For simple GenAI compatibility rewrites—such as copying or renaming legacy `gen_ai.system` to `gen_ai.provider.name`—use the `attributes` processor, or choose the upstream Collector distribution after verifying its component manifest. ### ECS Task Definition (sidecar container) ```json theme={"dark"} { "name": "adot-collector", "image": "public.ecr.aws/aws-observability/aws-otel-collector:latest", "essential": false, "command": ["--config", "/etc/otel/config.yaml"], "portMappings": [ { "containerPort": 4317, "protocol": "tcp" }, { "containerPort": 4318, "protocol": "tcp" } ] } ``` In a multi-container task, add a container dependency so the application starts only after the Collector is healthy. Grant the **task role** (not only the execution role) any permissions the application needs for Bedrock, and grant the execution role access to the Secrets Manager/SSM values injected into the task definition. With the receiver configuration above, an application sharing the task network can normally export to `http://localhost:4317` over gRPC or `http://localhost:4318` over HTTP. The exact host, port, protocol, and TLS settings depend on the task's network mode and your Collector configuration. *** ## Setup on EKS (DaemonSet) Deploy ADOT as a DaemonSet so one collector pod runs per node. Application pods export telemetry to the node's collector via the node IP or a local service. ```yaml theme={"dark"} apiVersion: apps/v1 kind: DaemonSet metadata: name: adot-collector namespace: monitoring spec: selector: matchLabels: app: adot-collector template: metadata: labels: app: adot-collector spec: containers: - name: adot-collector image: public.ecr.aws/aws-observability/aws-otel-collector:latest args: ["--config", "/etc/otel/config.yaml"] volumeMounts: - name: otel-config mountPath: /etc/otel volumes: - name: otel-config configMap: name: adot-config ``` Store the collector configuration above in a `ConfigMap` named `adot-config`. *** ## Log Data Organization ADOT attaches OpenTelemetry resource attributes to every signal. For **logs only**, Bronto maps `service.name` to a **Dataset** and `service.namespace` to a **Collection**. Metrics and traces are not stored in datasets or collections; view them in the [Metric Explorer](/metrics/explore-metrics) and [Explore Traces](/tracing/explore-traces). Set these in the `resource` block of your collector config: ```yaml theme={"dark"} processors: resource: attributes: - key: service.name value: action: upsert - key: service.namespace value: action: upsert ``` You can also override **log routing** on a logs exporter using HTTP headers, which is useful when one collector ships logs to multiple datasets: | Header | Description | | - | - | | `x-bronto-dataset` | Overrides `service.name` for the log dataset | | `x-bronto-collection` | Overrides `service.namespace` for the log collection | | `x-bronto-tags` | Comma-separated tags to attach to the log dataset | ```yaml theme={"dark"} exporters: otlphttp/brontologs: logs_endpoint: https://ingestion..bronto.io/v1/logs headers: x-bronto-api-key: x-bronto-dataset: x-bronto-collection: x-bronto-tags: env=prod,team=platform ``` *** ## Cost Notes * **No CloudWatch ingestion fees** — logs, metrics, and traces go directly from ADOT to Bronto over OTLP/HTTP. * **Compute cost only** — you pay for the ECS task or EKS pod running the collector, which is typically small relative to CloudWatch PUT and ingestion charges at scale. * Compare with the [CloudWatch Log Forwarder](./aws-client-cloudwatch) if your services already write to CloudWatch and the migration cost outweighs the savings. *** For assistance, contact [support@bronto.io](mailto:support@bronto.io). # Serverless Telemetry with ADOT Lambda Layer Source: https://docs.bronto.io/integrations/aws-adot-lambda Instrument AWS Lambda functions with the AWS Distro for OpenTelemetry (ADOT) Lambda Layer to send serverless logs, metrics, and traces to Bronto. ## When to Use the ADOT Lambda Layer The ADOT Lambda Layer is the **recommended** Lambda ingestion path when your function runtime supports the OpenTelemetry SDK. It is a good fit when you want to: * Send **logs, metrics, and traces** from AWS Lambda directly to Bronto via OTLP, without going through CloudWatch * Avoid CloudWatch ingestion fees on Lambda log volume * Use the same `service.name` / `service.namespace` identity across Lambda, ECS, and EKS workloads The layer captures logs emitted through the OpenTelemetry logging API in your function code (for example, via the OTel SDK or a bridged framework logger). Lambda's automatic `stdout` / `stderr` capture still goes to CloudWatch — to also ship those, use the [CloudWatch Log Forwarder](./aws-client-cloudwatch) alongside the layer, or route your application logger through OTel. *** ## Supported AWS Services The ADOT Lambda Layer is Lambda-specific: | Service | Data types | | - | - | | AWS Lambda | Function logs (via OTel SDK) and traces (auto-instrumented via the layer) | Supported runtimes are listed in the [ADOT Lambda documentation](https://aws-otel.github.io/docs/getting-started/lambda) — currently Node.js, Python, Java, .NET, and Go. For runtimes without OTel SDK support (Ruby, custom runtimes), use the [CloudWatch Log Forwarder](./aws-client-cloudwatch). For non-Lambda compute, see [ADOT — ECS / EKS](./aws-adot) or the [overview](./aws-overview). *** ## What is the ADOT Lambda Layer? The [ADOT Lambda Layer](https://aws-otel.github.io/docs/getting-started/lambda) is an AWS Lambda Layer that wraps your function with an embedded OpenTelemetry Collector. It can export logs, metrics, and traces to an OTLP-compatible backend — including Bronto. The exact automatically generated signals depend on the runtime instrumentation included in the layer version. *** ## Bronto OTLP Endpoints | Region | Logs Endpoint | Metrics Endpoint | Traces Endpoint | | - | - | - | - | | EU | `https://ingestion.eu.bronto.io/v1/logs` | `https://ingestion.eu.bronto.io/v1/metrics` | `https://ingestion.eu.bronto.io/v1/traces` | | US | `https://ingestion.us.bronto.io/v1/logs` | `https://ingestion.us.bronto.io/v1/metrics` | `https://ingestion.us.bronto.io/v1/traces` | The `/v1/logs`, `/v1/metrics`, and `/v1/traces` endpoints accept **OTLP protobuf only**. All requests require the header: ``` x-bronto-api-key: ``` See [API Keys](/Account-Management/API-Keys) for how to generate a key. *** ## Setup ### Step 1 — Add the ADOT Lambda Layer Add the ADOT managed Lambda Layer to your function. Layer ARNs are region- and architecture-specific. Find the latest ARN for your runtime in the [official ADOT Lambda Layer documentation](https://aws-otel.github.io/docs/getting-started/lambda#find-your-layer-arn). Via AWS CLI: ```bash theme={"dark"} aws lambda update-function-configuration \ --function-name \ --layers ``` Via Terraform: ```hcl theme={"dark"} resource "aws_lambda_function" "example" { # ... other config ... layers = [""] } ``` ### Step 2 — Configure the collector to export to Bronto Set the `OPENTELEMETRY_COLLECTOR_CONFIG_URI` environment variable to point to a collector config stored in S3 or SSM Parameter Store, or use inline configuration. Minimal collector config: ```yaml theme={"dark"} receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 processors: batch: exporters: otlphttp/bronto: logs_endpoint: "https://ingestion..bronto.io/v1/logs" metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" traces_endpoint: "https://ingestion..bronto.io/v1/traces" compression: none headers: x-bronto-api-key: service: pipelines: logs: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] metrics: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] traces: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] ``` ### Step 3 — Set environment variables on your Lambda function | Variable | Value | | - | - | | `OPENTELEMETRY_COLLECTOR_CONFIG_URI` | S3 URI or SSM path to your collector config | | `AWS_LAMBDA_EXEC_WRAPPER` | `/opt/otel-handler` (or runtime-specific wrapper — see ADOT docs) | ### Step 4 — Instrument your application code Add the OTel SDK for your runtime and configure it to export to the local collector. `localhost:4317` is the standard OTLP/gRPC default used by this example; use the actual receiver port and protocol if you customize the extension. For per-language setup instructions, see the [OpenTelemetry SDK guides](/opentelemetry/overview). *** ## Resource Identity and Log Organization The Lambda Layer attaches OpenTelemetry resource attributes to every signal. For **logs only**, Bronto maps `service.name` to a **Dataset** and `service.namespace` to a **Collection**. Metrics and traces use these attributes for identity and filtering, but are not stored in datasets or collections. Set these via Lambda environment variables — the OTel SDK reads them automatically: | Variable | All signals | Additional behavior for logs only | | - | - | - | | `OTEL_SERVICE_NAME` | Sets `service.name` | Selects the log dataset | | `OTEL_RESOURCE_ATTRIBUTES` | Sets additional resource attributes | `service.namespace` selects the log collection | You can also override log routing in the collector config using HTTP headers on the logs exporter: | Header | Description | | - | - | | `x-bronto-dataset` | Overrides `service.name` for the log dataset | | `x-bronto-collection` | Overrides `service.namespace` for the log collection | | `x-bronto-tags` | Comma-separated tags to attach to the log dataset | ```yaml theme={"dark"} exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" headers: x-bronto-api-key: x-bronto-dataset: x-bronto-collection: x-bronto-tags: env=prod,function= ``` *** ## Cost Notes * The ADOT Lambda Layer itself is free. * Logs, metrics, and traces sent through the layer bypass CloudWatch entirely — no CloudWatch ingestion fees for those exported signals. * Lambda's automatic `stdout` / `stderr` capture still writes to CloudWatch by default. To stop paying for that, route your application logger through the OTel SDK; to keep both paths, add the [CloudWatch Log Forwarder](./aws-client-cloudwatch) alongside the layer. *** For assistance, contact [support@bronto.io](mailto:support@bronto.io). # Amazon Bedrock AgentCore Logs, Metrics and Traces Source: https://docs.bronto.io/integrations/aws-agentcore Route the OpenTelemetry logs, metrics and traces an agent emits on Amazon Bedrock AgentCore Runtime to Bronto — via an OTel Collector or directly over OTLP. Agents running on [Amazon Bedrock AgentCore](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/what-is-bedrock-agentcore.html) Runtime emit OpenTelemetry telemetry through a **managed pipeline** that, by default, delivers to **Amazon CloudWatch**. To send that telemetry to Bronto you disable the managed pipeline and export OTLP to Bronto — either directly from the runtime or through an OTel Collector. Unlike log-only AWS services, there is no CloudWatch log group or Firehose stream to point at Bronto for the rich agent signal. The nested GenAI traces — model calls, token usage, tool calls, and prompt/response content — are produced by the agent framework's instrumentation running inside the runtime. ## Two requirements Configure the OpenTelemetry SDK inside your agent and take AWS's managed observability out of the way (`agentcore configure --disable-otel` plus `DISABLE_ADOT_OBSERVABILITY=true` at runtime), so your own exporters own the signal. For the full setup — the trace/metric/log providers, GenAI attributes, and making prompt/response content searchable — see [Amazon Bedrock AgentCore observability with OpenTelemetry](/ai-features/aws-agentcore). The instrumented runtime exports OTLP to an OTel Collector, which holds the Bronto credential and forwards each signal to Bronto. Where you don't operate a Collector, the runtime can export straight to Bronto with the credential in the request header. ## Recommended method [**ADOT**](./aws-adot) — the AWS Distro for OpenTelemetry Collector — receives OTLP from your agent and forwards logs, metrics and traces to Bronto over OTLP/HTTP. The Collector holds the Bronto credential so it never lives in the runtime config, and it keeps `service.name` / `service.namespace` identity consistent across signals. Only logs use those attributes for dataset and collection routing. It is also where you add processors, sampling, or fan-out to multiple backends; the [Self-Managed OTel Collector](./aws-custom-otel) is the same pattern for full-control deployments. Point the agent's OTLP exporters at the Collector (`OTEL_EXPORTER_OTLP_ENDPOINT`) rather than at Bronto directly. AgentCore's managed public network mode requires an internet-reachable endpoint; a proven pattern is ADOT on ECS Fargate behind a public HTTPS ALB. Configure the ALB health check against the Collector's health extension, not its OTLP receiver. See [Amazon Bedrock AgentCore observability with OpenTelemetry](/ai-features/aws-agentcore) for the SDK bootstrap and environment variables. The fully-managed AgentCore Runtime does not host a Collector sidecar and cannot reach a private VPC-only Collector in its public network mode. Expose the Collector securely over HTTPS, or use direct export below. ## LLM observability for AgentCore For the agent-specific signal — nested agent-loop traces, per-model token usage, tool calls, and prompt/response content following the OpenTelemetry GenAI semantic conventions — see [Amazon Bedrock AgentCore observability](/ai-features/aws-agentcore) under AI assisted observability. ## Alternatives * **Direct OTLP export from the runtime** — for the fully-managed runtime with no Collector to hand, or for short-lived jobs, export OTLP straight to Bronto: set `OTEL_EXPORTER_OTLP_ENDPOINT` to the Bronto ingestion base and inject the `x-bronto-api-key` header, sourced from [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/) at startup. No Collector, VPC, NAT, or sidecar is required — the agent's telemetry ships at full fidelity straight from the runtime. * **Keep the managed CloudWatch pipeline** — if you leave AgentCore's default observability enabled, its telemetry lands in CloudWatch; you can then forward those log groups with the [CloudWatch Log Forwarder](./aws-client-cloudwatch). This is a fallback: it does not preserve the nested trace fidelity that exporting OTLP to Bronto gives you. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon Bedrock AgentCore observability](/ai-features/aws-agentcore) * [Amazon Bedrock AgentCore documentation](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/what-is-bedrock-agentcore.html) * [AWS Distro for OpenTelemetry](https://aws-otel.github.io/) * [OpenTelemetry GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) # ALB and NLB Access Logs Source: https://docs.bronto.io/integrations/aws-alb Ingest Application and Network Load Balancer access logs into Bronto — client IP, request details, target, latency, and response code — from an S3 bucket. Application Load Balancers and Network Load Balancers can publish access logs to an S3 bucket. Each entry records the client IP and port, the request line, the chosen target, latency at each hop, and the response code — a comprehensive trail of the traffic that reached your load balancer. ## Recommended method [**S3 Log Forwarder**](./aws-client-s3) — enable access logging on each load balancer with a destination bucket, then point the Bronto forwarder Lambda at the bucket. New log objects are picked up via S3 event notifications and streamed into Bronto. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Application Load Balancer — access logs](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html) # Amazon API Gateway Logs Source: https://docs.bronto.io/integrations/aws-api-gateway Send execution and access logs from Amazon API Gateway REST and HTTP APIs to Bronto via CloudWatch, capturing request paths, latencies, and integration errors. Amazon API Gateway emits two log streams: **execution logs** (request handling, integration latency, errors) and **access logs** (request/response details with custom format strings). Both are written to CloudWatch Log Groups. ## Recommended method [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — enable execution and access logging on each API stage and the Bronto forwarder Lambda subscribes to the CloudWatch Log Groups and streams events into Bronto. ## Alternatives * [**Kinesis Firehose**](./aws-firehose-logs) — for high-volume access logs. Access logging writes to CloudWatch Logs; add a subscription filter on the access-log group targeting a Firehose stream. Choose the **JSON** access-log format so Bronto flattens fields automatically — a CLF/CSV/XML format is stored raw and requires a [custom parser](/core-features/custom-parser). See [Supported record formats](./aws-firehose-logs#supported-record-formats). See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon API Gateway — set up logging](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html) # Amazon Bedrock Logs, Metrics and Traces Source: https://docs.bronto.io/integrations/aws-bedrock Collect OpenTelemetry logs, metrics, and traces from applications that call the Amazon Bedrock Converse and InvokeModel APIs via an OTel Collector. Amazon Bedrock model invocations (the `Converse`, `ConverseStream`, `InvokeModel`, and `InvokeModelWithResponseStream` APIs) do not emit telemetry to Bronto on their own. You collect Bedrock telemetry by **instrumenting the application that calls Bedrock** with OpenTelemetry and forwarding it to Bronto through an **OTel Collector**. This is different from log-only AWS services: there is no CloudWatch log group or Firehose stream to point at Bronto. The rich GenAI signal — model id, token usage, latency, and prompt/response content — is produced by instrumenting your code. ## Two requirements Add the OpenTelemetry SDK and the AWS SDK auto-instrumentation to the service that calls Bedrock. The botocore/AWS SDK instrumentation traces `Converse` / `InvokeModel` calls and, on a recent enough version, enriches them with GenAI semantic-convention attributes (token usage, model, finish reason). See [Amazon Bedrock LLM observability with OpenTelemetry](/ai-features/aws-bedrock) for the full setup. The instrumented app exports OTLP to a Collector, which adds the Bronto credentials and forwards each signal to Bronto. On AWS the recommended Collector is [ADOT](./aws-adot), run as a sidecar (ECS / Fargate) or daemonset (EKS). ## Recommended method [**ADOT**](./aws-adot) — the AWS Distro for OpenTelemetry Collector — receives OTLP from your application and forwards logs, metrics and traces to Bronto over OTLP/HTTP, with consistent `service.name` / `service.namespace` identity. Only logs use those attributes for dataset and collection routing. The same sidecar pattern works on the [ECS / Fargate](./aws-ecs) and [EKS](./aws-eks) launch types you are likely already running your Bedrock app on. Pair it with application instrumentation for your language: How application instrumentation maps each signal to its Bronto destination. Most common runtime for Bedrock apps; richest GenAI auto-instrumentation. Instrument a Node.js service that calls the Bedrock APIs. All OTLP-capable runtimes export to the same Collector. ## LLM observability for Bedrock For the GenAI-specific signal — capturing token usage, model metadata, and prompt/response content following the OpenTelemetry GenAI semantic conventions — see [Amazon Bedrock LLM observability](/ai-features/aws-bedrock) under AI assisted observability. ## Alternatives * [**Self-managed OTel Collector**](./aws-custom-otel) — when you need custom processors, sampling, or fan-out to multiple backends alongside Bronto. * **Direct export** — for local development or short-lived jobs you can export OTLP straight from the SDK to Bronto with an API key; see the [direct export section](/opentelemetry/python#direct-export-to-bronto) on any language page. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon Bedrock Converse API](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html) * [AWS Distro for OpenTelemetry](https://aws-otel.github.io/) * [OpenTelemetry GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/aws-bedrock.md) # Forwarding AWS Logs from CloudWatch Source: https://docs.bronto.io/integrations/aws-client-cloudwatch Forward Amazon CloudWatch Logs to Bronto with Lambda subscription filters to centralize AWS service, application, and Lambda function logs for search. ## When to Use The CloudWatch Log Forwarder is a good fit when: * Your AWS services already deliver logs to CloudWatch (Lambda, RDS, ECS, API Gateway, VPC Flow Logs, and others) * You want a simple setup without changing how your services log * You are comfortable with the CloudWatch ingestion fees that apply to your log volume If you want to avoid CloudWatch ingestion fees for new workloads, consider [ECS FireLens](./aws-firelens), [Fluent Bit on EKS](./aws-fluent-bit-eks), or [ADOT](./aws-adot) instead. See the [overview](./aws-overview) for a full cost and method comparison. *** ## Supported AWS Services The CloudWatch Log Forwarder is the recommended path for any AWS service that publishes logs to CloudWatch Logs: | Service | Log type | | - | - | | AWS Lambda | Function `stdout` / `stderr` (for functions not using the [ADOT Lambda Layer](./aws-adot-lambda)) | | Amazon RDS / Aurora (PostgreSQL) | Database engine and slow-query logs | | Amazon RDS / Aurora (MySQL) | Error, slow-query, and general logs | | Amazon API Gateway | Execution and access logs | | Amazon ElastiCache | Engine and slow logs | | Amazon Route 53 | DNS query logs | | Amazon SES | Sending event logs | | AWS Step Functions | State machine execution logs | | Amazon Cognito | User pool authentication logs | | VPC Flow Logs | Network flow records (CloudWatch delivery) | | AWS WAF | Web ACL traffic logs (CloudWatch delivery) | Any service that can deliver to a CloudWatch log group is supported. See the [AWS documentation on services that publish to CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AWS-logs-and-resource-policy.html) for the full list. *** ## How it Works The Bronto AWS Log Forwarder is built around an AWS Lambda function that processes and forwards logs to Bronto. The function is triggered through CloudWatch [subscription filters](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SubscriptionFilters.html). Both log group level and [account level](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SubscriptionFilters-AccountLevel.html) subscription filters are supported. Bronto recommends using **account level subscription filters** so all log groups are forwarded automatically without per-group configuration. *** ## Setup Instructions Choose your preferred deployment method: **Terraform (recommended)** — Deploys the Lambda forwarder along with the necessary IAM roles and policies. Supports routing different log types to different destinations within Bronto. Full details and usage instructions are in the [Terraform module repository](https://github.com/brontoio/brontobytes-aws-ingestion-terraform). **CloudFormation** — Use the [CloudFormation template](https://s3.eu-west-1.amazonaws.com/brontobytes.io/integration/aws/cloudformation/1.0.0/brontoForwarder.yaml) in the AWS Console to create the stack by filling out a form. **Manual** — The Lambda function code and a pre-packaged deployment artifact are available in the [GitHub repository](https://github.com/brontoio/brontobytes-aws-ingestion-python). Set up account level subscription filters to automatically forward all CloudWatch log groups to the deployed Lambda function. Refer to the [AWS documentation on subscription filters](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SubscriptionFilters-AccountLevel.html) for setup steps. *** ## Data Organization The forwarder Lambda controls how data lands in Bronto through its configuration, not via HTTP headers — it composes the `x-bronto-*` headers internally based on the log group name and the per-source mapping you provide. See [Data Organization](/Search-and-Visualize/Partitions) for how datasets, collections, and tags work in Bronto. By default, with an account-level subscription filter (the recommended setup): * **Dataset** is the CloudWatch log group name (e.g. `/aws/lambda/`). * **Collection** is whatever you set as the default — `cloudwatch_default_collection` — or Bronto's default collection if not set. * **Tags** come from the global `bronto_tags` map. Provide a `destination_config` entry only when you want to override the defaults for a specific log group, or to apply per-source tags. ### Configure via Terraform (recommended) Set defaults and any per-log-group overrides via the [Terraform module](https://github.com/brontoio/brontobytes-aws-ingestion-terraform#usage): ```hcl theme={"dark"} module "bronto_aws_log_forwarding" { source = "git::https://github.com/brontoio/brontobytes-aws-ingestion-terraform.git//aws_log_forwarder" # ... bronto_api_key, artifact_bucket, etc. cloudwatch_default_collection = "Cloudwatch" account_level_cloudwatch_subscription = { enable = true excluded_log_groups = ["log_group1", "log_group2"] } # Optional — only needed to override defaults for specific log groups destination_config = { "/aws/lambda/" = { dataset = "" collection = "" log_type = "cloudwatch_log" tags = { team = "platform" } } } bronto_tags = { environment = "production", region = "eu-west-1" } } ``` * `cloudwatch_default_collection` sets the Bronto collection for any log group not explicitly listed in `destination_config`. * `account_level_cloudwatch_subscription` is the recommended way to forward all log groups automatically. AWS allows only one account-level subscription, so this is only suitable if no other account-level subscription is already in place. * `bronto_tags` apply globally; per-source `tags` inside a `destination_config` entry add or override tags for that log group only. * For log groups that need their own subscription filter pattern, set `set_individual_subscription = true` and `subscription_filter_pattern = ""` inside the matching `destination_config` entry. A `default_subscription_filter_pattern` can be applied to every account-level subscription. For the full variable reference, see the [Terraform module README](https://github.com/brontoio/brontobytes-aws-ingestion-terraform#usage). ### Configure direct Lambda deployments If you deploy the [Python Lambda](https://github.com/brontoio/brontobytes-aws-ingestion-python/blob/main/README.md) directly (CloudFormation or manual), the same configuration is provided as Lambda environment variables: | Environment variable | Purpose | | - | - | | `bronto_api_key` | Bronto API key | | `bronto_endpoint` | Regional ingestion endpoint, e.g. `https://ingestion.eu.bronto.io/` | | `cloudwatch_default_collection` | Default Bronto collection for CloudWatch log groups | | `destination_config` | Base64-encoded JSON map of log group names to `dataset`, `collection`, `log_type: cloudwatch_log`, and optional `tags` — only needed for overrides | | `tags` | Comma-separated `key=value` pairs applied to all datasets — e.g. `environment=production,region=eu-west-1` | See the [Python forwarder README](https://github.com/brontoio/brontobytes-aws-ingestion-python/blob/main/README.md) for a sample `destination_config` payload and the full attribute reference. *** ## Cost Notes * AWS charges for CloudWatch log ingestion (PUT requests and GB ingested to CloudWatch). These fees apply regardless of whether you forward the logs to Bronto. * Lambda invocation costs for the forwarder itself are minimal. * If CloudWatch ingestion costs are a concern at your log volume, see [ECS FireLens](./aws-firelens), [Fluent Bit on EKS](./aws-fluent-bit-eks), or [ADOT](./aws-adot) for alternatives that bypass CloudWatch entirely. *** For assistance, contact [support@bronto.io](mailto:support@bronto.io). # Forwarding AWS Logs from S3 Source: https://docs.bronto.io/integrations/aws-client-s3 Forward logs delivered to Amazon S3 buckets into Bronto using a Lambda-based forwarder for VPC flow, ALB, CloudFront, and other AWS service logs. ## When to Use The S3 Log Forwarder is a good fit when: * AWS services deliver log files directly to an S3 bucket (CloudFront, ALB, NLB, VPC Flow Logs, and others) * You want a low-complexity setup with no CloudWatch ingestion fees * You prefer Terraform or CloudFormation for infrastructure deployment For application logs or traces from running workloads, see [ECS FireLens](./aws-firelens), [ADOT](./aws-adot), or the [overview](./aws-overview) for a full comparison. *** ## Supported AWS Services The S3 Log Forwarder is the recommended path for AWS services that deliver logs directly to S3: | Service | Log type | | - | - | | Amazon CloudFront | Standard access logs | | Application Load Balancer (ALB) | Access logs | | Network Load Balancer (NLB) | Access logs | | VPC Flow Logs | Network flow records (S3 delivery) | | AWS WAF | Web ACL traffic logs | | AWS CloudTrail | Management and data event log files | | AWS GuardDuty | Findings export | | Amazon S3 | Server access logs | Any other AWS service that delivers logs to an S3 bucket can use this forwarder. See the [AWS documentation on services that publish to S3](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AWS-logs-and-resource-policy.html) for the full list. *** ## How it Works The Bronto AWS Log Forwarder is built around an AWS Lambda function that processes and forwards logs to Bronto. The function is triggered through S3 or EventBridge event notifications when new objects are written to your bucket. Supported AWS log sources include AWS CloudFront, Application Load Balancer (ALB), Network Load Balancer (NLB), VPC Flow Logs, and others. See the [AWS documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AWS-logs-and-resource-policy.html) for the full list of services that deliver to S3. *** ## Setup Instructions Choose your preferred deployment method: **Terraform (recommended)** — Deploys the Lambda forwarder along with the necessary IAM roles and policies. Supports routing different log types to different destinations within Bronto. Full details and usage instructions are in the [Terraform module repository](https://github.com/brontoio/brontobytes-aws-ingestion-terraform). **CloudFormation** — Use the [CloudFormation template](https://s3.eu-west-1.amazonaws.com/brontobytes.io/integration/aws/cloudformation/1.0.0/brontoForwarder.yaml) in the AWS Console to create the stack by filling out a form. **Manual** — The Lambda function code and a pre-packaged deployment artifact are available in the [GitHub repository](https://github.com/brontoio/brontobytes-aws-ingestion-python). Configure your S3 bucket to trigger the Lambda function when new objects are created. Refer to the [AWS documentation on S3 notifications](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enable-event-notifications.html) for setup steps. *** ## Data Organization The forwarder Lambda controls how data lands in Bronto through its configuration, not via HTTP headers — it composes the `x-bronto-*` headers internally based on the per-source mapping you provide. See [Data Organization](/Search-and-Visualize/Partitions) for how datasets, collections, and tags work in Bronto. ### Configure via Terraform (recommended) Map each S3 source (bucket name or CloudFront distribution ID) to its target dataset, collection, and log type using the `destination_config` variable on the [Terraform module](https://github.com/brontoio/brontobytes-aws-ingestion-terraform#usage): ```hcl theme={"dark"} module "bronto_aws_log_forwarding" { source = "git::https://github.com/brontoio/brontobytes-aws-ingestion-terraform.git//aws_log_forwarder" # ... bronto_api_key, artifact_bucket, logging_bucket, etc. destination_config = { "" = { dataset = "" collection = "" log_type = "s3_access_log" } "" = { dataset = "" collection = "" log_type = "cf_standard_access_log" } } bronto_tags = { environment = "production", region = "eu-west-1" } } ``` * `dataset` / `collection` route each source's logs to a specific Bronto destination. * `log_type` tells the forwarder which parser to apply — supported values include `s3_access_log`, `alb_access_log`, `nlb_access_log`, `clb_access_log`, `vpc_flow_log`, `cloudtrail`, `cf_standard_access_log`, `cf_realtime_access_log`, `bedrock_s3`, and `default` (no parsing, for already-structured JSON). * `bronto_tags` apply globally to all datasets produced by this forwarder. A per-source `tags` map inside a `destination_config` entry adds or overrides tags for that source only. * For sources whose S3 object keys don't match the default AWS naming patterns (for example, logs moved between buckets), use `paths_regex` with a `dest_config_id` capture group to map them to `destination_config` entries. For the full variable reference, see the [Terraform module README](https://github.com/brontoio/brontobytes-aws-ingestion-terraform#usage). ### Configure direct Lambda deployments If you deploy the [Python Lambda](https://github.com/brontoio/brontobytes-aws-ingestion-python/blob/main/README.md) directly (CloudFormation or manual), the same configuration is provided as Lambda environment variables: | Environment variable | Purpose | | - | - | | `bronto_api_key` | Bronto API key | | `bronto_endpoint` | Regional ingestion endpoint, e.g. `https://ingestion.eu.bronto.io/` | | `destination_config` | Base64-encoded JSON mapping S3 resource names to `dataset`, `collection`, `log_type`, and optional `tags` | | `tags` | Comma-separated `key=value` pairs applied to all datasets — e.g. `environment=production,region=eu-west-1` | | `paths_regex` | Base64-encoded list of regex patterns for non-standard S3 key layouts | See the [Python forwarder README](https://github.com/brontoio/brontobytes-aws-ingestion-python/blob/main/README.md) for a sample `destination_config` payload and the full attribute reference. *** ## Cost Notes * No CloudWatch ingestion fees — logs are read directly from S3 by the Lambda function. * You pay for S3 storage and Lambda invocations, both of which are minimal for typical log volumes. *** For assistance, contact [support@bronto.io](mailto:support@bronto.io). # Amazon CloudFront Real-Time Logs Source: https://docs.bronto.io/integrations/aws-cloudfront Stream Amazon CloudFront real-time logs to Bronto with per-viewer-request edge details such as cache status, edge location, viewer IP, and response bytes. Amazon CloudFront can emit logs in two distinct shapes: **real-time logs** (per-request details including cache status, edge location, URI, status code, and time to first byte, streamed within seconds) and **standard access logs** (a similar shape with delayed batch delivery — minutes to hours). Standard logging is available in two versions: **v1** delivers to S3 only, while **v2** also supports CloudWatch Logs and Kinesis Data Firehose as destinations. ## Recommended method [**Kinesis Firehose**](./aws-firehose-logs) — real-time logs deliver to a Kinesis Data Stream, which Firehose then forwards to Bronto. This is the only path that preserves the low-latency stream. CloudFront real-time log records arrive **TAB-delimited and positional** (fields in the fixed order configured in the real-time log configuration; unselected fields rendered as `-`). Bronto stores them raw but does **not** extract fields automatically. Build a [custom parser](/core-features/custom-parser) that splits on tab and maps columns to your configured field list, in order. See [Formats requiring a custom parser](./aws-firehose-logs#formats-requiring-a-custom-parser). ## Alternatives * [**S3 Log Forwarder**](./aws-client-s3) — for **standard access logs** (v1, or v2 routed to S3). Different schema and delayed delivery; not equivalent to real-time logs. * [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — for standard access logs (v2) routed to a CloudWatch Log Group. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon CloudFront — real-time logs](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/real-time-logs.html) # AWS CloudTrail Events Source: https://docs.bronto.io/integrations/aws-cloudtrail Ingest AWS API activity and management events from CloudTrail into Bronto — who did what, when, and from where — via EventBridge API Destinations. AWS CloudTrail records API activity and management events across your AWS account — who called what, when, from which source IP, and with which result. CloudTrail is the canonical audit trail and is also the underlying source for service-level activity logs ([DynamoDB](./aws-dynamodb), [Cognito](./aws-cognito), and others). ## Recommended method [**EventBridge API Destinations**](./aws-eventbridge) — a CloudTrail-driven EventBridge rule delivers events to Bronto in real time over HTTPS, with no intermediate storage. ## Alternatives * [**S3 Log Forwarder**](./aws-client-s3) — CloudTrail's native destination; the forwarder Lambda subscribes to the trail's bucket and ships new objects. * [**Kinesis Firehose**](./aws-firehose-logs) — for very high event volumes. Enable *Send to CloudWatch Logs* on the trail, then add a subscription filter on the trail's log group targeting a Firehose stream. CloudTrail events are JSON, so Bronto flattens them into searchable fields automatically — no parser needed. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [AWS CloudTrail — log file examples](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-log-file-examples.html) # Amazon CloudWatch Metrics Source: https://docs.bronto.io/integrations/aws-cloudwatch-metrics Ingest Amazon CloudWatch service metrics for EC2, RDS, Lambda, and load balancers into Bronto through CloudWatch Metric Streams and Amazon Data Firehose. Amazon CloudWatch provides metrics for AWS services and resources, including EC2, RDS, Lambda, load balancers, and other managed services. Bronto ingests these metrics through a CloudWatch Metric Stream that uses the OpenTelemetry 1.0 output format and delivers to Bronto through Amazon Data Firehose. ## Recommended method [**AWS Kinesis Firehose for CloudWatch Metrics**](./aws-firehose-cloudwatch-metrics) — create a CloudWatch Metric Stream, select the AWS metrics and namespaces you want to export, and use a Firehose HTTP destination to deliver the OpenTelemetry 1.0 payloads to Bronto. This managed path is intended for metrics already available in CloudWatch. It requires no Lambda function and supports both Bronto EU and US environments. Bronto supports sums, gauges, summaries, and explicit histograms. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). ## Application and infrastructure metrics For application-instrumented metrics or infrastructure metrics collected directly from hosts and containers, use [ADOT](./aws-adot) or a [Self-Managed OpenTelemetry Collector](./aws-custom-otel). These options can send logs, metrics, and traces together and avoid routing workload telemetry through CloudWatch. See [Host Metrics](/integrations/host-metrics) and the [OpenTelemetry Collector Contrib receivers](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver) for supported infrastructure sources. ## Verify metrics After the selected CloudWatch namespaces emit data, open **Metric Explorer** in Bronto and select a recently emitted AWS metric. Confirm that the expected AWS dimensions, timestamp, and any optional Bronto tags are present. ## Further reading * [AWS Kinesis Firehose for CloudWatch Metrics](./aws-firehose-cloudwatch-metrics) * [Amazon CloudWatch metrics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/working_with_metrics.html) * [Amazon CloudWatch Metric Streams](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Metric-Streams.html) * [OpenTelemetry metrics concepts](https://opentelemetry.io/docs/concepts/signals/metrics/) * [Send Metrics to Bronto](/metrics/send-metrics) See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. # Amazon Cognito Activity Source: https://docs.bronto.io/integrations/aws-cognito Ingest Amazon Cognito user pool activity — authentication events, user management operations, and token issuance — via CloudTrail. Amazon Cognito doesn't emit logs of its own — instead, user pool authentication events, user management operations, and token issuance are recorded in [AWS CloudTrail](./aws-cloudtrail). ## Recommended method [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — configure CloudTrail to deliver Cognito events to a CloudWatch Log Group, and the Bronto forwarder Lambda streams them into Bronto. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon Cognito — logging API calls with CloudTrail](https://docs.aws.amazon.com/cognito/latest/developerguide/logging-using-cloudtrail.html) # Self-Managed OpenTelemetry Collector on AWS Source: https://docs.bronto.io/integrations/aws-custom-otel Deploy and configure an OpenTelemetry Collector on AWS to send logs, metrics, and traces to Bronto with full control over routing and processing. ## When to Use a Self-Managed Collector A self-managed OpenTelemetry Collector is a good fit when you need: * **Full configuration control** — custom processors, attribute transformation, or sampling rules * **Fan-out** — forwarding the same telemetry to multiple backends simultaneously * **Existing OTel infrastructure** — you already operate a collector fleet and want to add Bronto as an exporter * **Advanced log routing** — sending logs from different types or services to different Bronto datasets or collections If you want a simpler, AWS-managed setup without manual configuration, consider [ADOT](./aws-adot) instead. Application logs, metrics, and traces can be sent directly to Bronto, but routing through a Collector is strongly recommended for retries, batching, and compression. *** ## Supported AWS Services A self-managed Collector can run anywhere you control compute, and supports any source that has an OpenTelemetry receiver: | Service / Source | Data types | | - | - | | Amazon EC2 | Application logs, traces, metrics, and host metrics | | Amazon ECS / Fargate | Application logs, metrics, and traces (sidecar or dedicated task) | | Amazon EKS | Application logs, metrics, and traces (DaemonSet or Deployment) | | Any AWS workload reachable from the Collector | Logs / traces via OTLP, file, Kafka, Kinesis, Pub/Sub, and other [OTel receivers](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver) | Use this method when ADOT or the Bronto-managed forwarders don't cover your scenario. For Lambda traces specifically, the [ADOT Lambda Layer](./aws-adot-lambda) is simpler. The Collector forwards only what it receives — deploying it does not automatically collect your logs. If you aren't seeing all the logs you expect: * **Application logs, metrics, and traces** require instrumenting your app with the [OpenTelemetry SDK](/opentelemetry/overview), or tailing its log files with the `filelog` receiver. * **Infrastructure and database logs** (web servers, proxies, databases, message brokers) each have their own Collector setup — see [Ingesting Infrastructure and Database Logs](./infrastructure-overview). * **AWS platform and service logs** (CloudTrail, VPC Flow Logs, RDS, and other managed services) are exported through AWS-native forwarders, not the Collector — see [Ingesting AWS Data into Bronto](./aws-overview) for the per-service source-to-method mapping. *** ## Bronto Ingestion Endpoints | Signal | EU Region | US Region | | - | - | - | | Logs | `https://ingestion.eu.bronto.io/v1/logs` | `https://ingestion.us.bronto.io/v1/logs` | | Metrics | `https://ingestion.eu.bronto.io/v1/metrics` | `https://ingestion.us.bronto.io/v1/metrics` | | Traces | `https://ingestion.eu.bronto.io/v1/traces` | `https://ingestion.us.bronto.io/v1/traces` | The `/v1/logs`, `/v1/metrics`, and `/v1/traces` endpoints accept **OTLP protobuf only**. All requests require the header: ``` x-bronto-api-key: ``` See [API Keys](/Account-Management/API-Keys) for how to generate a key. *** ## Collector Configuration The core Bronto exporter configuration is the same regardless of how you deploy the collector on AWS. For full installation instructions, platform-specific configuration, and parameter reference, see the [OpenTelemetry Collector guide](/agent-setup/open-telemetry). The minimal configuration exports logs, metrics, and traces to Bronto: ```yaml theme={"dark"} receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: exporters: otlphttp/bronto: logs_endpoint: "https://ingestion..bronto.io/v1/logs" metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" traces_endpoint: "https://ingestion..bronto.io/v1/traces" compression: none headers: x-bronto-api-key: service: pipelines: logs: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] metrics: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] traces: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] ``` Replace `` with `eu` or `us` and `` with your Bronto API key. *** ## Deployment Options on AWS ### EC2 Install the OpenTelemetry Collector directly on your EC2 instances following the [official installation guide](https://opentelemetry.io/docs/collector/installation/). Place your config at `/etc/otel/config.yaml` and run the collector as a systemd service. ### ECS (Sidecar or Daemon) Run the collector as a sidecar container alongside each application task, or as a daemon service on each ECS instance. Use the standard `otel/opentelemetry-collector-contrib` image and mount your config via S3 or SSM Parameter Store. ### EKS (DaemonSet or Deployment) Deploy as a DaemonSet (one collector per node) for node-level log collection, or as a Deployment behind a ClusterIP service for centralised collection. Store your config in a ConfigMap and reference it as a volume mount. ```yaml theme={"dark"} apiVersion: v1 kind: ConfigMap metadata: name: otel-config namespace: monitoring data: config.yaml: | # paste your collector config here ``` *** ## Log Data Organization OpenTelemetry resource attributes provide shared identity across logs, metrics, and traces. For **logs only**, Bronto maps `service.name` to a **Dataset** and `service.namespace` to a **Collection**. Metrics and traces are not stored in datasets or collections; view them in the [Metric Explorer](/metrics/explore-metrics) and [Explore Traces](/tracing/explore-traces). Set these as resource attributes in your SDK or collector config: ```yaml theme={"dark"} processors: resource: attributes: - key: service.name value: action: upsert - key: service.namespace value: action: upsert ``` You can also override **log routing** on a logs exporter using HTTP headers, which is useful when one collector ships logs to multiple datasets: | Header | Description | | - | - | | `x-bronto-dataset` | Overrides `service.name` for the log dataset | | `x-bronto-collection` | Overrides `service.namespace` for the log collection | | `x-bronto-tags` | Comma-separated tags to attach to the log dataset | ```yaml theme={"dark"} exporters: otlphttp/brontologs: logs_endpoint: https://ingestion..bronto.io/v1/logs headers: x-bronto-api-key: x-bronto-dataset: x-bronto-collection: x-bronto-tags: env=prod,team=platform ``` For Kubernetes logs, set `x-bronto-collection` to your cluster name (e.g. `cluster1-prod-eu-west-1`) to identify the source cluster in Bronto. *** For assistance or questions, contact [support@bronto.io](mailto:support@bronto.io). # Amazon DynamoDB Events Source: https://docs.bronto.io/integrations/aws-dynamodb Ingest Amazon DynamoDB management and data events — API calls, table operations, and item-level activity — into Bronto through CloudTrail and EventBridge. Amazon DynamoDB doesn't emit logs of its own — instead, table operations, control-plane API calls, and (when enabled) item-level data events are recorded in [AWS CloudTrail](./aws-cloudtrail). DynamoDB Streams is a separate, application-facing change-data-capture feature for items in a table. This page covers operational and audit-event ingestion via CloudTrail; DynamoDB Streams is out of scope here. ## Recommended method [**EventBridge API Destinations**](./aws-eventbridge) — a CloudTrail-driven EventBridge rule delivers DynamoDB events to Bronto in real time over HTTPS, with no intermediate storage. ## Alternatives * [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — when CloudTrail is configured to publish to a CloudWatch Log Group. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon DynamoDB — logging API calls with CloudTrail](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/logging-using-cloudtrail.html) # Amazon ECS and AWS Fargate Telemetry Source: https://docs.bronto.io/integrations/aws-ecs Choose the right ingestion path for container logs, metrics, and traces from Amazon ECS tasks and AWS Fargate workloads — an ADOT sidecar or FireLens. Amazon ECS and AWS Fargate emit container `stdout` / `stderr` logs from your tasks, plus distributed traces when your applications are instrumented with OpenTelemetry. ## Recommended method [**ADOT**](./aws-adot) — run the OpenTelemetry Collector as a sidecar to send logs, metrics, and traces directly to Bronto over OTLP. It bypasses CloudWatch and gives Lambda, ECS, and EKS workloads consistent resource identity. ## Alternatives * [**ECS FireLens**](./aws-firelens) — Fluent Bit sidecar that ships logs from your task; lighter operational footprint than a full collector. * [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — for tasks that already write to CloudWatch Log Groups via the `awslogs` driver. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon ECS — using FireLens for log routing](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_firelens.html) # Amazon EKS Telemetry Source: https://docs.bronto.io/integrations/aws-eks Choose the right ingestion path for pod logs, kubelet metrics, control plane logs, and traces from Amazon EKS — an ADOT DaemonSet or Fargate sidecar. Amazon EKS workloads emit pod logs and application telemetry, while the kubelet exposes node, pod, container, and volume metrics. Control-plane logs are written to CloudWatch by AWS. ## Recommended method [**ADOT**](./aws-adot) — deploy the Collector as a DaemonSet on EC2 node groups to collect pod logs, kubelet metrics, and application telemetry. On Fargate, use a per-pod sidecar because DaemonSets cannot run there. See [Kubernetes logs and metrics](/integrations/kubernetes) for the kubelet preset and RBAC requirements. ## Alternatives * [**Fluent Bit on EKS**](./aws-fluent-bit-eks) — DaemonSet that collects container logs from every node; lighter than a full collector. * [**Self-Managed OTel Collector**](./aws-custom-otel) — full control over the OpenTelemetry pipeline when ADOT's distribution doesn't fit. * [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — required path for EKS control plane logs, which are CloudWatch-only. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon EKS — control plane logs](https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html) # Amazon ElastiCache Logs Source: https://docs.bronto.io/integrations/aws-elasticache Ship Amazon ElastiCache slow logs and engine logs for Redis and Valkey clusters to Bronto to troubleshoot latency, evictions, and command usage. Amazon ElastiCache for Redis and Valkey can publish two log streams: the **slow log** (commands that exceeded a configured execution threshold) and the **engine log** (server events). Both can be delivered to CloudWatch Log Groups or to Amazon Data Firehose. ElastiCache for Memcached doesn't emit these log streams. ## Recommended method [**Kinesis Firehose**](./aws-firehose-logs) — enable log delivery for the slow log and/or engine log on the cluster, destination **Amazon Data Firehose**. Both log streams are supported. Select the **JSON** log format on the AWS side. Bronto parses and flattens JSON records automatically — no parser needed. The **TEXT** format is comma-delimited and stored raw, requiring a [custom parser](/core-features/custom-parser). See [Supported record formats](./aws-firehose-logs#supported-record-formats). ## Alternatives * [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — enable slow log and engine log delivery to CloudWatch on the cluster, and the Bronto forwarder Lambda subscribes to the resulting log groups. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon ElastiCache — log delivery](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/Log_Delivery.html) # AWS EventBridge API Destinations Source: https://docs.bronto.io/integrations/aws-eventbridge Route AWS service events directly to Bronto using Amazon EventBridge API Destinations, with no Lambda function required for forwarding or transformation. ## When to Use EventBridge EventBridge API Destinations are a good fit when you want to: * Forward **AWS service events** into Bronto without writing or maintaining a Lambda function * Ingest audit and compliance data such as CloudTrail events, GuardDuty findings, or AWS Config change notifications * React to ECS task state changes, EC2 instance events, or other AWS operational events in near real-time For application logs or traces from running workloads, use [ADOT](./aws-adot), [FireLens](./aws-firelens), or the [CloudWatch Log Forwarder](./aws-client-cloudwatch) instead. *** ## Supported AWS Services EventBridge API Destinations work with any AWS service that publishes to the default event bus: | Service | Log / event type | | - | - | | AWS CloudTrail | Management and data event audit records | | AWS GuardDuty | Security threat findings | | Amazon DynamoDB | Table state changes (via CloudTrail) | | AWS Config | Resource configuration change events | | Amazon ECS | Task and container state changes | | Amazon EC2 | Instance state change notifications | | AWS Health | Service health and scheduled maintenance events | | AWS Step Functions | State machine execution events | | AWS WAF | Rule match events (via CloudTrail) | Any other AWS service that publishes events to EventBridge can be captured by adding the appropriate rule pattern. See the [AWS documentation on EventBridge event sources](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-service-event.html) for the full list. *** ## How it Works [EventBridge API Destinations](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-api-destinations.html) allow EventBridge rules to POST matched events directly to any HTTP endpoint. You define: 1. A **Connection** — stores the authentication credentials (your Bronto API key) 2. An **API Destination** — points to Bronto's ingestion endpoint using the connection 3. A **Rule** — matches the AWS events you want to capture and targets the API Destination EventBridge delivers events as JSON payloads, handled retries natively, and requires no Lambda or additional infrastructure. *** ## Bronto Ingestion Endpoint EventBridge posts JSON payloads, so it targets the Bronto base endpoint (no path), which accepts JSON: | Region | Endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | Do not use the `/v1/logs` path with EventBridge. That endpoint accepts only OTLP protobuf via an OTel-compatible agent. EventBridge sends JSON and must target the base endpoint. See [API Keys](/Account-Management/API-Keys) for how to generate a key. *** ## Setup ### Step 1 — Create an EventBridge Connection The connection stores your Bronto API key as a custom authorisation header. In the AWS Console, go to **EventBridge → API Destinations → Connections → Create connection**: | Field | Value | | - | - | | Connection name | `bronto-connection` | | Authorization type | `API Key` | | API key name | `x-bronto-api-key` | | API key value | `` | Via AWS CLI: ```bash theme={"dark"} aws events create-connection \ --name bronto-connection \ --authorization-type API_KEY \ --auth-parameters '{ "ApiKeyAuthParameters": { "ApiKeyName": "x-bronto-api-key", "ApiKeyValue": "" } }' ``` ### Step 2 — Create an API Destination In **EventBridge → API Destinations → Create API destination**: | Field | Value | | - | - | | Name | `bronto-destination` | | API destination endpoint | `https://ingestion..bronto.io` | | HTTP method | `POST` | | Connection | `bronto-connection` (from Step 1) | | Rate limit | Set based on your expected event volume | ### Step 3 — Create an EventBridge Rule Create a rule that matches the events you want to forward and targets the API Destination. Example: forward all CloudTrail management events: ```json theme={"dark"} { "source": ["aws.cloudtrail"], "detail-type": ["AWS API Call via CloudTrail"] } ``` Example: forward GuardDuty findings: ```json theme={"dark"} { "source": ["aws.guardduty"], "detail-type": ["GuardDuty Finding"] } ``` Set the rule target to the `bronto-destination` API Destination created in Step 2. *** ## Data Organization EventBridge Connections support custom HTTP headers via `InvocationHttpParameters`. Use these to set Bronto's recommended headers — see [Data Organization](/Search-and-Visualize/Partitions) for how datasets, collections, and tags work. | Header | Description | | - | - | | `x-bronto-dataset` | Dataset to ingest into | | `x-bronto-collection` | Collection name | | `x-bronto-tags` | Comma-separated tags to attach to events | Add them when creating or updating the Connection: ```bash theme={"dark"} aws events update-connection \ --name bronto-connection \ --auth-parameters '{ "ApiKeyAuthParameters": { "ApiKeyName": "x-bronto-api-key", "ApiKeyValue": "" }, "InvocationHttpParameters": { "HeaderParameters": [ { "Key": "x-bronto-dataset", "Value": "", "IsValueSecret": false }, { "Key": "x-bronto-collection", "Value": "", "IsValueSecret": false }, { "Key": "x-bronto-tags", "Value": "env=prod,source=eventbridge", "IsValueSecret": false } ] } }' ``` To route different rules to different datasets, create one Connection per dataset and attach a separate API Destination to each. *** ## Cost Notes * No Lambda compute cost — EventBridge delivers events directly. * You pay for EventBridge custom event publishing and API Destination invocations, which are typically very low cost relative to log ingestion alternatives. *** For assistance, contact [support@bronto.io](mailto:support@bronto.io). # AWS Kinesis Firehose for CloudWatch Metrics Source: https://docs.bronto.io/integrations/aws-firehose-cloudwatch-metrics Send Amazon CloudWatch metrics to Bronto through CloudWatch Metric Streams and an Amazon Data Firehose HTTP destination — no Lambda function required. ## Overview [CloudWatch Metric Streams](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Metric-Streams.html) can continuously export AWS service metrics to Amazon Data Firehose. Configure the metric stream to use the OpenTelemetry 1.0 output format, then configure Firehose to deliver those metrics to Bronto's dedicated AWS metrics endpoint. This integration requires no Lambda function. Firehose handles batching, compression, and retries for delivery to Bronto. Bronto supports sums, gauges, summaries, and explicit histograms. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). ## Prerequisites Before you begin, you need: * a Bronto API key with the ingestion role * your Bronto region: `eu` or `us` * permission to create or configure Firehose delivery streams, CloudWatch Metric Streams, and their IAM service roles See [API Keys](/Account-Management/API-Keys) for how to generate a key. ## Step 1 — Create a Firehose delivery stream In the AWS Console, go to **Amazon Data Firehose → Create Firehose stream** and configure: | Setting | Value | | - | - | | Source | **Direct PUT** | | Destination | **HTTP Endpoint** | | Firehose stream name | Any valid, unique name | `cw-metrics-to-bronto` is a suggested name only. You can use a different name that follows your organization's naming conventions. Create a Firehose stream with Direct PUT as the source and HTTP Endpoint as the destination ## Step 2 — Configure the Bronto HTTP endpoint Configure the HTTP endpoint destination: | Setting | Value | | - | - | | HTTP endpoint URL | `https://ingestion..bronto.io/aws/metrics` | | Access key | A Bronto API key with the ingestion role | | Content encoding | **GZIP** | Replace `` with `eu` or `us`. For example, use `https://ingestion.eu.bronto.io/aws/metrics` for the EU environment or `https://ingestion.us.bronto.io/aws/metrics` for the US environment. Do not use the direct OTLP `/v1/metrics` endpoint for this Firehose workflow. Optionally, add `x-bronto-tags` in the destination's **Parameters** section to attach comma-separated tags to the ingested metrics, for example `environment=staging,region=eu-west-1`. Let Firehose create a service role, or select an existing role with the permissions required to deliver to the HTTP endpoint. See AWS's [HTTP endpoint destination settings](https://docs.aws.amazon.com/firehose/latest/dev/create-destination.html) for further reading. ## Step 3 — Create a CloudWatch metric stream In the CloudWatch console, go to **Metrics → Streams**, then choose **Create metric stream**. CloudWatch navigation with Metrics and Streams selected Choose **Custom setup with Firehose**, select the Firehose delivery stream created in Step 1, and let CloudWatch create a service role or select an existing role that can write to the stream. CloudWatch metric stream configured with a custom Firehose destination Set the output format to **OpenTelemetry 1.0**. Choose **All metrics** or select only the metric namespaces and metrics you want to send. In a CloudWatch monitoring account, you can also choose to include metrics from linked source accounts. This option applies to the Region in which you create the stream. CloudWatch Metric Streams always include the `Minimum`, `Maximum`, `SampleCount`, and `Sum` statistics. Additional statistics can be configured in CloudWatch at additional cost. CloudWatch charges per metric update streamed, and Firehose charges for the data it processes. Streaming all metrics can be expensive in accounts with many metrics. Select only the namespaces you need when practical. CloudWatch metric stream using the OpenTelemetry 1.0 output format Enter a metric stream name and create the stream. `cw-metrics-stream-to-firehose` is a suggested name only; it is not required. Suggested CloudWatch metric stream name For AWS's complete setup instructions, including IAM and infrastructure-as-code options, see [Custom setup with Firehose](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-metric-streams-setup-datalake.html). ## Automate with AWS CloudFormation Use the [Bronto CloudWatch Metrics deployment package](https://github.com/bronto-community/bronto-cloudwatch-metrics) to create and update filtered metric streams across multiple AWS accounts and Regions. For each configured target, the package creates the CloudWatch Metric Stream, encrypted Firehose delivery stream and failure-backup bucket, CloudWatch delivery logs, and required IAM roles. It supports AWS CLI profiles that use direct credentials or assume roles into target accounts, and resolves the Bronto API key from AWS Secrets Manager without reading or copying it into the deployment script. See the repository's [README](https://github.com/bronto-community/bronto-cloudwatch-metrics#readme) for prerequisites, configuration options, example targets, filtering, dry-run deployments, linked-account metrics, retention settings, and guidance for larger AWS Organizations environments. ## Verify metric ingestion After the selected CloudWatch namespaces emit data, open **Metric Explorer** in Bronto and select a recently emitted AWS metric. Confirm that its timestamp, dimensions, and optional `x-bronto-tags` values are present. Allow for the Firehose buffering interval before troubleshooting delivery. If delivery fails, open the `/aws/kinesisfirehose/` log group in CloudWatch Logs and inspect the `HttpEndpointDelivery` stream. Firehose records the HTTP response code and Bronto response details there. A valid Firehose endpoint response must use HTTP `200`, contain an uncompressed `application/json` body, and return the request's `requestId` with a numeric `timestamp`. See [HTTP endpoint request and response specifications](https://docs.aws.amazon.com/firehose/latest/dev/httpdeliveryrequestresponse.html) and [HTTP endpoint troubleshooting](https://docs.aws.amazon.com/firehose/latest/dev/http_troubleshooting.html). For supported metric types, current limitations, direct OTLP configuration, and links to the upstream OpenTelemetry documentation, see [Send Metrics](/metrics/send-metrics). ## Further reading * [Amazon CloudWatch metrics](./aws-cloudwatch-metrics) * [Amazon CloudWatch Metric Streams](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Metric-Streams.html) * [Custom setup with Firehose](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-metric-streams-setup-datalake.html) * [OpenTelemetry metrics concepts](https://opentelemetry.io/docs/concepts/signals/metrics/) * [Send Metrics to Bronto](/metrics/send-metrics) *** For assistance, contact [support@bronto.io](mailto:support@bronto.io). # AWS Kinesis Firehose for Logs Source: https://docs.bronto.io/integrations/aws-firehose-logs Stream high-volume AWS logs into Bronto with an Amazon Data Firehose delivery stream that batches and retries HTTP delivery automatically. ## Overview Bronto's Kinesis Firehose integration lets you stream logs directly from an [Amazon Data Firehose](https://docs.aws.amazon.com/firehose/latest/dev/what-is-this-service.html) delivery stream into Bronto over HTTP. It is well suited to high-throughput pipelines where data already flows through Kinesis, services that deliver natively to Firehose, and CloudWatch-native services routed to Firehose through a subscription filter. The integration requires no Lambda function. Firehose delivers data directly to Bronto's HTTP endpoint, handling batching, compression, and retries natively. To export CloudWatch metrics rather than logs, use [AWS Kinesis Firehose for CloudWatch Metrics](./aws-firehose-cloudwatch-metrics). ## When to Use Firehose | Situation | Recommendation | | - | - | | Data already in a Kinesis Data Stream | Firehose is the natural choice | | A service that delivers natively to Firehose | Firehose captures the full-fidelity record | | Very high event volume (GB/hour+) | Firehose scales without additional Lambda cost | | You want managed delivery with built-in retries | Firehose handles this natively | | Application or container logs | Use [ADOT](./aws-adot) or the [CloudWatch Log Forwarder](./aws-client-cloudwatch) instead | For low or moderate volume sources, the [S3 Log Forwarder](./aws-client-s3) or [CloudWatch Log Forwarder](./aws-client-cloudwatch) are simpler to operate. *** ## Bronto Ingestion Endpoint Firehose delivers to Bronto's dedicated AWS HTTP endpoint: | Region | Endpoint URL | | - | - | | EU | `https://ingestion.eu.bronto.io/aws/logs/` | | US | `https://ingestion.us.bronto.io/aws/logs/` | Configure the delivery stream's HTTP endpoint destination as follows: | Setting | Value | | - | - | | HTTP endpoint URL | `https://ingestion..bronto.io/aws/logs/` | | Access key | Your Bronto API key — sent by Firehose in the `X-Amz-Firehose-Access-Key` header | | Content encoding | **GZIP** | See [API Keys](/Account-Management/API-Keys) for how to generate a key. No `log_format` parameter is needed. Bronto auto-detects the payload shape — it unwraps CloudWatch Logs subscription envelopes and parses JSON record bodies automatically. See [Supported record formats](#supported-record-formats) below. A successful delivery returns `200` with `Content-Type: application/json` and a body of the form `{"requestId":"","timestamp":}`. Firehose may send up to 500 records per request. *** ## Data Organization Set Bronto's routing headers as the HTTP endpoint **Common attributes** on the delivery stream. Firehose delivers them in the `X-Amz-Firehose-Common-Attributes` JSON header. See [Data Organization](/Search-and-Visualize/Partitions) for how datasets, collections, and tags work. | Common attribute | Description | | - | - | | `x-bronto-dataset` | Dataset to ingest into | | `x-bronto-collection` | Collection name | | `x-bronto-tags` | Comma-separated tags to attach to events | To route different sources to different datasets, deploy a separate Firehose delivery stream per dataset and set its common attributes accordingly. *** ## Supported record formats Bronto detects field extraction from the **record body**, not the service that produced it. Two tiers of record body are decoded automatically; delimited and positional text formats are stored raw and require a [custom parser](/core-features/custom-parser). ### CloudWatch Logs subscription format Services that reach Firehose through **CloudWatch Logs → subscription filter → Firehose** deliver a gzip-compressed CloudWatch Logs subscription envelope (`DATA_MESSAGE` containing one or more `logEvents`). Bronto unwraps it automatically: * One stored event per `logEvent`. * CloudWatch Logs metadata is preserved under `$logGroup`, `$logStream`, `$messageType`, `$owner`, and related fields. * Firehose delivery metadata is preserved under `$firehose.requestId`, `$firehose.sourceArn`, and `$firehose.timestamp`. * Each `logEvent` message is then parsed by its own format — JSON bodies are flattened (below), delimited text is stored raw. This covers every service that exports via a CloudWatch Logs subscription filter, including CloudTrail, RDS/Aurora, API Gateway, and Route 53 public query logging. ### JSON record bodies Records delivered directly to Firehose as JSON objects are parsed and flattened into searchable fields, with nested keys expressed in dot notation (for example `mail.destination.0`, `answers.0.Rdata`, `httpRequest.clientIp`). No configuration is required. Verified for Amazon SES events, Route 53 Resolver query logs, AWS WAF logs (native JSON), and ElastiCache logs **when the JSON log format is selected** on the AWS side. AWS requires a WAF logging delivery stream's name to start with `aws-waf-logs-` before WAF will accept it as a destination. ### Formats requiring a custom parser Delimited and positional text records are accepted and stored raw (in `@raw`) but are **not** field-extracted automatically. Each requires a Bronto [custom parser](/core-features/custom-parser): | Source | Record shape | | - | - | | CloudFront real-time logs | TAB-delimited, fixed field order, unselected fields rendered as `-` | | Route 53 public query logging | Space-delimited line | | RDS / Aurora plain-text logs | PostgreSQL `stderr`, MySQL slow-query blocks, Aurora audit CSV (heterogeneous) | | ElastiCache TEXT format | Comma-delimited | | VPC Flow Logs | Space-delimited v2 positional line (`version account-id interface-id srcaddr dstaddr …`) | For positional formats (CloudFront real-time logs, VPC Flow Logs), the custom parser must be pinned to the exact field list and order configured on the AWS side — the order is fixed, but the selected subset varies per configuration, so map columns 1:1. Where a service offers a JSON log format (ElastiCache, API Gateway), prefer it to avoid writing a parser. *** ## Setup ### Step 1 — Create the Firehose delivery stream In the AWS Console, go to **Amazon Data Firehose → Create Firehose stream**. Choose the **source** that matches your service: * **Direct PUT** — for services that publish directly to Firehose (SES, Route 53 Resolver, ElastiCache). * **Amazon Kinesis Data Streams** — for CloudFront real-time logs, which deliver to a Kinesis Data Stream first. Set the **destination** to **HTTP Endpoint**. Create Firehose stream with source Direct PUT and destination HTTP Endpoint ### Step 2 — Configure the HTTP endpoint destination | Field | Value | | - | - | | HTTP endpoint URL | `https://ingestion..bronto.io/aws/logs/` | | Access key | `` | | Content encoding | `GZIP` | Destination settings: Bronto HTTP endpoint URL, access key, and GZIP content encoding In the destination's **Parameters** section (Firehose delivers these as the `X-Amz-Firehose-Common-Attributes` header), add `x-bronto-collection`, `x-bronto-dataset`, and optionally `x-bronto-tags`. No `log_format` parameter is needed — Bronto auto-detects the payload shape. Parameters section with x-bronto-collection, x-bronto-dataset, and x-bronto-tags key-value pairs ### Step 3 — Connect the source (CloudWatch-native services) For services that have no native Firehose export (CloudTrail, RDS/Aurora, API Gateway, Route 53 public query logging), first publish the service's logs to a CloudWatch log group, then add a **subscription filter** on that log group targeting the Firehose stream. The subscription filter needs an IAM role trusting `logs.amazonaws.com` with permission to `firehose:PutRecord*` on the delivery stream. CloudWatch Logs already compresses subscription data with gzip. Do not add a second compression layer in the delivery stream's data transformation — set only the destination content encoding to GZIP as above. For native-Firehose services, configure the service's own event/log destination to point at the delivery stream (see the per-service pages: [SES](./aws-ses), [CloudFront](./aws-cloudfront), [Route 53](./aws-route53), [ElastiCache](./aws-elasticache)). *** ## Cost Firehose pricing is based on the volume of data processed through the delivery stream (per GB). There are no Lambda compute costs. Services routed through CloudWatch Logs incur standard CloudWatch Logs ingestion charges in addition to Firehose costs. *** For assistance, contact [support@bronto.io](mailto:support@bronto.io). # ECS Container Logs with AWS FireLens Source: https://docs.bronto.io/integrations/aws-firelens Route Amazon ECS container logs directly to Bronto using AWS FireLens with Fluent Bit, skipping CloudWatch and reducing AWS log ingestion costs. ## When to Use FireLens FireLens is a good fit when you are running workloads on ECS and want to: * Ship container `stdout` / `stderr` logs directly to Bronto without going through CloudWatch * Keep your setup **log-focused** without the overhead of an OTel pipeline * Use AWS's native ECS log routing rather than managing a separate collector If you also need **metrics or traces** from your ECS workloads, use [ADOT](./aws-adot), which handles logs, metrics, and traces through one Collector. *** ## Supported AWS Services FireLens routes logs from containers running in: | Service | Log type | | - | - | | Amazon ECS (EC2 launch type) | Container `stdout` / `stderr` | | AWS Fargate | Container `stdout` / `stderr` | FireLens is ECS-specific. For EKS container logs, use [Fluent Bit on EKS](./aws-fluent-bit-eks). For Lambda or other AWS services, see the [overview](./aws-overview). *** ## What is FireLens? [AWS FireLens](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_firelens.html) is an ECS log routing feature that uses a Fluent Bit (or Fluentd) sidecar container as a log driver. Container logs are piped from your application containers directly to the FireLens sidecar, which forwards them to Bronto using JSON Lines over HTTPS. FireLens runs as a sidecar in the same ECS task. No separate infrastructure is required. *** ## Bronto Ingestion Endpoint FireLens uses Fluent Bit's `http` output, which sends JSON Lines to the Bronto base endpoint (no path): | Region | Endpoint | | - | - | | EU | `ingestion.eu.bronto.io` | | US | `ingestion.us.bronto.io` | This is different from the OTLP endpoints (`/v1/logs`, `/v1/metrics`, `/v1/traces`), which accept only protobuf and require an OTel-compatible agent. Fluent Bit's `http` output uses JSON Lines and must target the base endpoint. All requests require the header: ``` x-bronto-api-key: ``` See [API Keys](/Account-Management/API-Keys) for how to generate a key. *** ## Setup ### Step 1 — Add the FireLens sidecar to your task definition Add a `log_router` container using the AWS-provided Fluent Bit image. This container acts as the log driver for all other containers in the task. ```json theme={"dark"} { "name": "log-router", "image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:stable", "essential": true, "firelensConfiguration": { "type": "fluentbit", "options": { "enable-ecs-log-metadata": "true" } } } ``` ### Step 2 — Configure Fluent Bit to forward to Bronto Pass a custom Fluent Bit configuration to the sidecar via an S3 object or SSM Parameter Store. The output section targets Bronto's base ingestion endpoint using JSON Lines format. For the full Fluent Bit configuration reference and output options, see the [Fluent Bit setup guide](/agent-setup/fluent-bit). ```ini theme={"dark"} [OUTPUT] Name http Match * Host ingestion..bronto.io Port 443 Format json_lines Compress gzip tls On tls.verify On Header x-bronto-api-key Header x-bronto-dataset Header x-bronto-collection ``` Replace `` with `eu` or `us`. ### Step 3 — Point your application containers at FireLens Update the `logConfiguration` of each application container to use the `awsfirelens` log driver: ```json theme={"dark"} { "logConfiguration": { "logDriver": "awsfirelens", "options": { "Name": "http", "Host": "ingestion..bronto.io", "Port": "443", "Format": "json_lines", "Compress": "gzip", "tls": "On", "tls.verify": "On", "Header": "x-bronto-api-key " } } } ``` *** ## Data Organization Set the recommended headers in your Fluent Bit `[OUTPUT]` block to control how data lands in Bronto — see [Data Organization](/Search-and-Visualize/Partitions) for how datasets, collections, and tags work. | Header | Description | | - | - | | `x-bronto-dataset` | Dataset to ingest into | | `x-bronto-collection` | Collection name | | `x-bronto-tags` | Comma-separated tags to attach to events | ```ini theme={"dark"} [OUTPUT] Name http Match * Host ingestion..bronto.io Port 443 Format json_lines Compress gzip tls On tls.verify On Header x-bronto-api-key Header x-bronto-dataset Header x-bronto-collection Header x-bronto-tags env=prod,team=platform ``` To route different containers in the same task to different datasets, define multiple `[OUTPUT]` blocks with different `Match` patterns and per-output `Header` directives. *** ## Cost Notes * **No CloudWatch ingestion fees** — logs go directly from FireLens to Bronto. * You pay only for the ECS task compute running the FireLens sidecar, which is negligible. * Compare with [CloudWatch Log Forwarder](./aws-client-cloudwatch) if your services already write to CloudWatch. *** For assistance, contact [support@bronto.io](mailto:support@bronto.io). # Kubernetes Logs with Fluent Bit on EKS Source: https://docs.bronto.io/integrations/aws-fluent-bit-eks Deploy Fluent Bit as a DaemonSet on Amazon EKS to collect Kubernetes container logs and forward them to Bronto, a lightweight alternative to the OTel Collector. ## When to Use Fluent Bit on EKS Fluent Bit as an EKS DaemonSet is a good fit when you want to: * Collect **container logs** from all pods on every node without modifying application code * Keep the setup simple — Fluent Bit is lighter and easier to configure than a full OTel Collector when you only need logs * Avoid CloudWatch log ingestion fees If you also need **traces** from your Kubernetes workloads, use the [Self-Managed OTel Collector](./aws-custom-otel) or [ADOT](./aws-adot) instead, as Fluent Bit does not handle trace data. *** ## Supported AWS Services Fluent Bit on EKS collects logs from containers running in: | Service | Log type | | - | - | | Amazon EKS (EC2 node groups) | Pod `stdout` / `stderr`, enriched with Kubernetes metadata | | Amazon EKS (Fargate) | Pod `stdout` / `stderr` (via Fargate-built-in log router) | For ECS container logs, use [ECS FireLens](./aws-firelens). For non-Kubernetes AWS services, see the [overview](./aws-overview). *** ## How it Works A Fluent Bit DaemonSet runs one pod per node. Each pod reads container logs from the node's `/var/log/containers/` path, enriches them with Kubernetes metadata (pod name, namespace, labels), and forwards them to Bronto using JSON Lines over HTTPS. For the full Fluent Bit configuration reference and output options, see the [Fluent Bit setup guide](/agent-setup/fluent-bit). *** ## Bronto Ingestion Endpoint Fluent Bit's `http` output sends JSON Lines to the Bronto base endpoint (no path): | Region | Endpoint | | - | - | | EU | `ingestion.eu.bronto.io` | | US | `ingestion.us.bronto.io` | This is different from the OTLP endpoints (`/v1/logs`, `/v1/traces`), which accept only protobuf and require an OTel-compatible agent. Fluent Bit's `http` output uses JSON Lines and must target the base endpoint. All requests require the header: ``` x-bronto-api-key: ``` See [API Keys](/Account-Management/API-Keys) for how to generate a key. *** ## Setup ### Step 1 — Deploy Fluent Bit via Helm The easiest way to deploy Fluent Bit on EKS is via the official Helm chart. ```bash theme={"dark"} helm repo add fluent https://fluent.github.io/helm-charts helm repo update helm install fluent-bit fluent/fluent-bit \ --namespace monitoring \ --create-namespace \ --values values.yaml ``` ### Step 2 — Configure the Bronto output Create a `values.yaml` file that configures Fluent Bit to tail container logs and forward them to Bronto: ```yaml theme={"dark"} config: inputs: | [INPUT] Name tail Path /var/log/containers/*.log multiline.parser docker, cri Tag kube.* Mem_Buf_Limit 5MB Skip_Long_Lines On filters: | [FILTER] Name kubernetes Match kube.* Kube_URL https://kubernetes.default.svc:443 Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token Merge_Log On Keep_Log Off K8S-Logging.Parser On K8S-Logging.Exclude On outputs: | [OUTPUT] Name http Match kube.* Host ingestion..bronto.io Port 443 Format json_lines Compress gzip tls On tls.verify On Header x-bronto-api-key Header x-bronto-collection tolerations: - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule ``` Replace `` with `eu` or `us`, `` with your Bronto API key, and `` with a name that identifies this cluster in Bronto (e.g. `cluster1-prod-eu-west-1`). ### Step 3 — Verify After deployment, logs should appear in Bronto Search. You can filter by `collection` to isolate logs from this cluster. ```bash theme={"dark"} kubectl get pods -n monitoring -l app.kubernetes.io/name=fluent-bit ``` All pods should show `Running` status. *** ## Data Organization Set the recommended headers in your Fluent Bit `[OUTPUT]` block to control how data lands in Bronto — see [Data Organization](/Search-and-Visualize/Partitions) for how datasets, collections, and tags work. | Header | Description | | - | - | | `x-bronto-dataset` | Dataset to ingest into | | `x-bronto-collection` | Collection name (typically your cluster name) | | `x-bronto-tags` | Comma-separated tags to attach to events | ```ini theme={"dark"} [OUTPUT] Name http Match kube.* Host ingestion..bronto.io Port 443 Format json_lines Compress gzip tls On tls.verify On Header x-bronto-api-key Header x-bronto-dataset Header x-bronto-collection Header x-bronto-tags env=prod,team=platform ``` By default, Bronto can also infer the dataset from Kubernetes metadata (container name, pod labels). To route logs from specific namespaces or pods to different datasets, add a `rewrite_tag` filter and configure multiple `[OUTPUT]` blocks with different `Match` patterns and `x-bronto-dataset` headers. See the [Fluent Bit setup guide](/agent-setup/fluent-bit) for full routing examples. *** ## Cost Notes * **No CloudWatch ingestion fees** — logs go directly from Fluent Bit to Bronto. * Fluent Bit is lightweight; the DaemonSet pods typically consume less than 50MB memory per node. *** ## EKS Fargate EKS Fargate works differently from EKS on EC2 node groups. There are no customer-managed nodes and the node filesystem isn't exposed to pods, so the DaemonSet pattern described above doesn't apply. AWS instead provides a built-in Fluent Bit log router, configured via a `ConfigMap` in the `aws-observability` namespace, that captures `stdout` / `stderr` from every Fargate pod cluster-wide. The constraint that shapes this section is that the Fargate built-in Fluent Bit accepts only a fixed allowlist of output plugins: * `cloudwatch` / `cloudwatch_logs` * `firehose` / `kinesis_firehose` * `kinesis` * `es` (Elasticsearch / OpenSearch) The `http` plugin — which would let Fluent Bit POST directly to Bronto's ingestion endpoint — is **not** on this allowlist, and any `ConfigMap` referencing it is rejected at admission time. This is a known AWS platform limitation tracked by [containers-roadmap#1242](https://github.com/aws/containers-roadmap/issues/1242), open since 2021. It affects every third-party log destination equally, not just Bronto. The restriction applies only to the AWS-managed Fluent Bit router. Your own OpenTelemetry Collector — running as an ordinary Kubernetes Deployment in the cluster — has no such restriction and can send to any HTTP endpoint, including Bronto. There are three viable paths for Fargate pod logs into Bronto. Most teams use a combination during and after migration. ### Path A — Fluent Bit → Kinesis Firehose → Bronto The Fargate built-in Fluent Bit writes to a Kinesis Firehose delivery stream, which forwards records to Bronto. ``` EKS Fargate Pods → Built-in Fluent Bit (kinesis_firehose) → Kinesis Firehose → Bronto ``` This is the most direct path available given Fargate's constraints — a single intermediate hop, both ends managed services. It uses Bronto's [Kinesis Firehose integration](./aws-firehose-logs). The `kinesis_firehose` plugin emits one JSON record per log line, so Bronto flattens the record's Kubernetes metadata into searchable fields automatically (`kubernetes.pod_name`, `kubernetes.namespace_name`, `kubernetes.labels.*`, `stream`) — no custom parser required. Enable `Merge_Log On` in the `kubernetes` filter so an application's structured JSON log line is merged into the record root and its fields are extracted too. Without it, the raw application line is preserved as a single `log` string. Example `ConfigMap` output block: ```ini theme={"dark"} [OUTPUT] Name kinesis_firehose Match kube.* region delivery_stream ``` Customers already running a Firehose pipeline (for example, currently writing logs to S3 or OpenSearch) can typically reuse the same Firehose stream by reconfiguring its destination, with no changes to the in-cluster Fluent Bit configuration. ### Path B — Fluent Bit → CloudWatch Logs → Bronto The Fargate built-in Fluent Bit writes to a CloudWatch log group, and the [Bronto CloudWatch Log Forwarder](./aws-client-cloudwatch) ingests events from that group. ``` EKS Fargate Pods → Built-in Fluent Bit (cloudwatch_logs) → CloudWatch Logs → Bronto Forwarder → Bronto ``` The trade-off versus Path A is the additional CloudWatch ingestion cost, which can be significant at high log volume. Path A avoids that cost by skipping CloudWatch entirely, so it is generally preferred for high-volume Fargate logging. Example `ConfigMap` output block: ```ini theme={"dark"} [OUTPUT] Name cloudwatch_logs Match kube.* region log_group_name /aws/eks//fargate log_stream_prefix from-fluent-bit- auto_create_group true ``` ### Path C — Application → OTel Collector → Bronto Applications emit log records over OTLP using the OpenTelemetry logs SDK, sending them directly to your existing OTel Collector. The collector then forwards to Bronto via OTLP/HTTP — the same exporter pattern used for traces. ``` Application (OTel logs SDK) → OTel Collector → Bronto ``` This path is the recommended direction for new services and for existing services where instrumentation is feasible. It bypasses the Fluent Bit allowlist entirely and gives trace-to-log correlation automatically. Logs and traces share `service.name` / `service.namespace` identity, but only logs use those attributes for dataset and collection routing. See [Self-Managed OTel Collector](./aws-custom-otel) for collector configuration and the [OpenTelemetry SDK guides](/opentelemetry/overview) for per-language instrumentation. Example collector logs pipeline (append `otlphttp/bronto-logs` to any existing logs pipeline): ```yaml theme={"dark"} exporters: otlphttp/bronto-logs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" headers: x-bronto-api-key: "${env:BRONTO_API_KEY}" x-bronto-collection: "" service: pipelines: logs: receivers: [otlp] processors: [memory_limiter, batch] exporters: [otlphttp/, otlphttp/bronto-logs] ``` Path C is **not** a fit for third-party container images you can't modify, short-lived init containers and jobs, runtimes where the OTel logs SDK is still maturing, or applications under heavy change-control. Workloads in those categories continue on Path A or Path B indefinitely — both remain fully supported. ### Running multiple destinations during migration The Fargate `ConfigMap` accepts multiple `[OUTPUT]` blocks, so logs can be sent to Bronto and an existing destination in parallel during cutover: ```ini theme={"dark"} output.conf: | # Existing destination — kept active during migration [OUTPUT] Name kinesis_firehose Match kube.* region delivery_stream # New destination — Bronto via a separate Firehose stream [OUTPUT] Name kinesis_firehose Match kube.* region delivery_stream ``` For Path C, the equivalent is listing multiple exporters in the OTel Collector's logs pipeline. ### Traces and metrics on Fargate Traces from Fargate workloads go through your in-cluster OTel Collector exactly as on EC2 node groups — add Bronto as an OTLP/HTTP exporter on the traces pipeline. See [ADOT](./aws-adot) or [Self-Managed OTel Collector](./aws-custom-otel) for collector deployment guidance. Add the Bronto metrics endpoint and exporter to the Collector's existing metrics pipeline. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). ```yaml theme={"dark"} exporters: otlphttp/bronto-metrics: metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" headers: x-bronto-api-key: service: pipelines: metrics: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto-metrics] ``` ### Summary | Signal | Path | Status | | - | - | - | | Logs (A) | Fluent Bit (built-in) → Kinesis Firehose → Bronto | GA | | Logs (B) | Fluent Bit (built-in) → CloudWatch Logs → Bronto | GA | | Logs (C) | Application (OTel logs SDK) → OTel Collector → Bronto | GA where applications can be instrumented | | Traces | Application → OTel Collector → Bronto | GA | | Metrics | Application → OTel Collector → Bronto | GA | Recommended starting point on EKS Fargate: 1. Add Bronto as an exporter on your existing OTel Collector for application logs, metrics, and traces. 2. Stand up a Fluent Bit log path in parallel — Path A (Firehose) for the lowest cost, or Path B (CloudWatch) if you already have a CloudWatch pipeline — and send to both your existing destination and Bronto until you've validated coverage. 3. Adopt Path C incrementally for new services and high-value existing services. Workloads that can't be instrumented stay on Path A or Path B. *** For assistance, contact [support@bronto.io](mailto:support@bronto.io). # AWS GuardDuty Findings Source: https://docs.bronto.io/integrations/aws-guardduty Ingest AWS GuardDuty threat findings into Bronto — compromised credentials, unusual API calls, malware, and suspicious network activity — via EventBridge. AWS GuardDuty produces findings — threat-intelligence alerts covering compromised credentials, unusual API calls, reconnaissance activity, malware on EC2 and EKS workloads, and other security events. ## Recommended method [**EventBridge API Destinations**](./aws-eventbridge) — GuardDuty publishes findings as EventBridge events, so a rule with an API Destination delivers them to Bronto in real time over HTTPS. ## Alternatives * [**S3 Log Forwarder**](./aws-client-s3) — for environments that already export findings to an S3 bucket via the GuardDuty findings-export feature. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [AWS GuardDuty — exporting findings](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_exportfindings.html) # AWS Lambda Telemetry Source: https://docs.bronto.io/integrations/aws-lambda Compare AWS Lambda ingestion options for function logs, platform logs, metrics, and traces to choose between CloudWatch, extensions, or the ADOT layer. AWS Lambda emits function logs (your application output), platform logs (cold starts, timeouts, out-of-memory events), and — when instrumented — distributed traces. The right ingestion path depends on your runtime and whether you also want traces. ## Recommended method [**ADOT Lambda Layer**](./aws-adot-lambda) — sends logs, metrics, and traces directly to Bronto over OTLP on supported runtimes. The signals generated automatically depend on the ADOT layer and instrumentation versions you deploy. ## Alternatives * [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — captures Lambda's automatic `stdout` / `stderr` and works with runtimes the ADOT layer doesn't support (Ruby, custom runtimes). See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [AWS Lambda — monitoring with CloudWatch Logs](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html) # Ingesting AWS Data into Bronto Source: https://docs.bronto.io/integrations/aws-overview An overview of the available methods for sending AWS log, trace, and metric data to Bronto, with guidance on choosing the right approach. ## Overview Bronto supports several methods for ingesting data from AWS environments. The right choice depends on where your logs originate, whether you need trace data, your infrastructure preferences, and cost constraints. *** ## Service-to-Method Mapping Different AWS services suit different ingestion methods. The recommended method is the simplest path that gets the data into Bronto; alternatives may be preferable depending on your existing infrastructure or cost constraints. Each service name in the table below links to a per-source landing page with a short summary of what the service emits and the configuration entry points for that data. Where the OpenTelemetry SDK supports your runtime, prefer OTel-based instrumentation — it sends logs, metrics, and traces through one Collector, gives you consistent resource identity, and avoids CloudWatch ingestion fees. The [ADOT Lambda Layer](./aws-adot-lambda) covers Lambda; [ADOT](./aws-adot) or a [Self-Managed OTel Collector](./aws-custom-otel) cover ECS, EKS, and EC2 workloads. | AWS Service | Recommended Method | Alternatives | | - | - | - | | [Amazon CloudWatch metrics](./aws-cloudwatch-metrics) | [Kinesis Firehose for CloudWatch Metrics](./aws-firehose-cloudwatch-metrics) (Metric Streams with OpenTelemetry 1.0) | [ADOT](./aws-adot) or [Self-Managed OTel Collector](./aws-custom-otel) for workload metrics | | [AWS Lambda](./aws-lambda) (logs + traces) | [ADOT Lambda Layer](./aws-adot-lambda) (OTel-supported runtimes) | [CloudWatch Log Forwarder](./aws-client-cloudwatch) (for stdout/stderr capture or unsupported runtimes) | | [Amazon ECS / Fargate](./aws-ecs) | [ADOT](./aws-adot) (OTel) | [ECS FireLens](./aws-firelens), [CloudWatch Log Forwarder](./aws-client-cloudwatch) | | [Amazon EKS](./aws-eks) | [ADOT](./aws-adot) (OTel) | [Fluent Bit on EKS](./aws-fluent-bit-eks), [Self-Managed OTel Collector](./aws-custom-otel), [CloudWatch Log Forwarder](./aws-client-cloudwatch) (control plane logs) | | [Amazon Bedrock](./aws-bedrock) (GenAI traces + logs) | [ADOT](./aws-adot) (OTel) — see [LLM observability](/ai-features/aws-bedrock) | Direct OTLP to Bronto, [Self-Managed OTel Collector](./aws-custom-otel) | | [Amazon Bedrock AgentCore](./aws-agentcore) (agent traces + logs) | [ADOT](./aws-adot) (OTel) — see [agent observability](/ai-features/aws-agentcore) | Direct OTLP to Bronto, [Self-Managed OTel Collector](./aws-custom-otel) | | [Amazon RDS / Aurora (PostgreSQL)](./aws-rds-postgresql) | [CloudWatch Log Forwarder](./aws-client-cloudwatch) | [Kinesis Firehose](./aws-firehose-logs) (high-volume) | | [Amazon RDS / Aurora (MySQL)](./aws-rds-mysql) | [CloudWatch Log Forwarder](./aws-client-cloudwatch) | [Kinesis Firehose](./aws-firehose-logs) (high-volume) | | [AWS CloudTrail](./aws-cloudtrail) | [EventBridge API Destinations](./aws-eventbridge) | [S3 Log Forwarder](./aws-client-s3), [Kinesis Firehose](./aws-firehose-logs) (high-volume) | | [Amazon API Gateway](./aws-api-gateway) | [CloudWatch Log Forwarder](./aws-client-cloudwatch) | [Kinesis Firehose](./aws-firehose-logs) (high-volume access logs) | | [ALB / NLB access logs](./aws-alb) | [S3 Log Forwarder](./aws-client-s3) | — | | [VPC Flow Logs](./aws-vpc-flow-logs) | [S3 Log Forwarder](./aws-client-s3) | [CloudWatch Log Forwarder](./aws-client-cloudwatch), [Kinesis Firehose](./aws-firehose-logs) (custom parser required) | | [AWS WAF](./aws-waf) | [S3 Log Forwarder](./aws-client-s3) | [Kinesis Firehose](./aws-firehose-logs) (native JSON), [CloudWatch Log Forwarder](./aws-client-cloudwatch) | | [Amazon DynamoDB](./aws-dynamodb) | [EventBridge API Destinations](./aws-eventbridge) (via CloudTrail) | [CloudWatch Log Forwarder](./aws-client-cloudwatch) | | [Amazon ElastiCache](./aws-elasticache) | [CloudWatch Log Forwarder](./aws-client-cloudwatch) | [Kinesis Firehose](./aws-firehose-logs) (high-volume) | | [Amazon CloudFront](./aws-cloudfront) (real-time logs) | [Kinesis Firehose](./aws-firehose-logs) | [S3 Log Forwarder](./aws-client-s3) (standard logs) | | [Amazon Route 53](./aws-route53) | [CloudWatch Log Forwarder](./aws-client-cloudwatch) (public zone query logs) | [Kinesis Firehose](./aws-firehose-logs) (Resolver query logs, JSON), [S3 Log Forwarder](./aws-client-s3) (Resolver query logs) | | [AWS GuardDuty](./aws-guardduty) | [EventBridge API Destinations](./aws-eventbridge) | [S3 Log Forwarder](./aws-client-s3) | | [Amazon SES](./aws-ses) | [Kinesis Firehose](./aws-firehose-logs) (full event bodies) | — | | [AWS Step Functions](./aws-step-functions) | [CloudWatch Log Forwarder](./aws-client-cloudwatch) | [EventBridge API Destinations](./aws-eventbridge) | | [Amazon Cognito](./aws-cognito) | [CloudWatch Log Forwarder](./aws-client-cloudwatch) | — | *** ## Ingestion Methods Bronto supports the following AWS ingestion methods: * [S3 Log Forwarder](./aws-client-s3) — Lambda subscribes to S3 events and forwards new log objects. * [CloudWatch Log Forwarder](./aws-client-cloudwatch) — Lambda subscribes to CloudWatch log groups and streams events. * [ECS FireLens](./aws-firelens) — Fluent Bit sidecar in your ECS task definitions; no Lambda required. * [Fluent Bit on EKS](./aws-fluent-bit-eks) — Fluent Bit DaemonSet that collects container logs from every EKS node. * [ADOT — ECS / EKS](./aws-adot) — AWS-managed OpenTelemetry Collector distribution for ECS and EKS workloads. * [ADOT Lambda Layer](./aws-adot-lambda) — OpenTelemetry instrumentation layer for AWS Lambda functions. * [Self-Managed OTel Collector](./aws-custom-otel) — Your own OpenTelemetry Collector deployment for full control. * [EventBridge API Destinations](./aws-eventbridge) — Native EventBridge rule that POSTs events directly to Bronto. * [AWS Kinesis Firehose for Logs](./aws-firehose-logs) — Direct delivery of high-volume AWS log records. * [AWS Kinesis Firehose for CloudWatch Metrics](./aws-firehose-cloudwatch-metrics) — Delivery of OpenTelemetry 1.0 CloudWatch Metric Streams. *** ## AWS VPC Private Link Bronto can be connected via an AWS VPC Private Link, keeping all traffic within the AWS network and avoiding public internet egress. This is available on request — contact [support@bronto.io](mailto:support@bronto.io) to set this up. # Amazon RDS and Aurora (MySQL) Logs Source: https://docs.bronto.io/integrations/aws-rds-mysql Ship MySQL slow query, general, and error logs from Amazon RDS and Aurora MySQL to Bronto to diagnose slow queries, connection failures, and replication issues. Amazon RDS and Aurora can publish MySQL logs — the slow query log, general log, and error log — to CloudWatch Log Groups, where they become available for ingestion. ## Recommended method [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — enable MySQL log exports on the DB instance or cluster and the Bronto forwarder Lambda subscribes to the resulting CloudWatch Log Groups and streams events into Bronto. ## Alternatives * [**Kinesis Firehose**](./aws-firehose-logs) — for very high-volume environments. Enable MySQL log exports to CloudWatch Logs, then add a subscription filter on each log group targeting a Firehose stream. MySQL logs arrive as plain text (slow-query blocks, error and general logs), so Bronto stores them raw and a [custom parser](/core-features/custom-parser) is required to extract fields. See [Formats requiring a custom parser](./aws-firehose-logs#formats-requiring-a-custom-parser). See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon RDS — MySQL log access](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.Concepts.MySQL.html) # Amazon RDS and Aurora (PostgreSQL) Logs Source: https://docs.bronto.io/integrations/aws-rds-postgresql Ship PostgreSQL slow query, connection, and error logs from Amazon RDS and Aurora to Bronto to troubleshoot query latency, locking, and auth failures. Amazon RDS and Aurora can publish PostgreSQL logs — slow queries, connections, errors, and autovacuum activity — to CloudWatch Log Groups, where they become available for ingestion. ## Recommended method [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — enable PostgreSQL log exports on the DB instance or cluster (`log_statement`, `log_min_duration_statement`, etc.) and the Bronto forwarder Lambda subscribes to the resulting CloudWatch Log Groups and streams events into Bronto. ## Alternatives * [**Kinesis Firehose**](./aws-firehose-logs) — for very high-volume environments. Enable PostgreSQL log exports to CloudWatch Logs, then add a subscription filter on the log group targeting a Firehose stream. PostgreSQL logs arrive as plain `stderr` text, so Bronto stores them raw and a [custom parser](/core-features/custom-parser) is required to extract fields. See [Formats requiring a custom parser](./aws-firehose-logs#formats-requiring-a-custom-parser). See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon RDS — PostgreSQL log access](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.Concepts.PostgreSQL.html) # Amazon Route 53 DNS Query Logs Source: https://docs.bronto.io/integrations/aws-route53 Ingest Amazon Route 53 public DNS query logs and Resolver query logs into Bronto to investigate DNS traffic patterns, resolver failures, and suspicious lookups. Amazon Route 53 produces two types of query logs with different delivery options and record shapes, so they take different ingestion paths: * **Resolver query logs** — for resolver endpoints in your VPCs. Can be delivered **directly to Kinesis Data Firehose** (also CloudWatch or S3). Records are **JSON**. * **Public DNS query logs** — for hosted zones (which queries hit which records). Written to **CloudWatch Logs only**. Records are a **space-delimited line**. ## Recommended method **Resolver query logs → [Kinesis Firehose](./aws-firehose-logs).** Configure the Resolver query-log configuration to deliver to a Firehose stream. Records arrive as JSON (`query_name`, `query_type`, `rcode`, `answers[]`, `srcaddr`, …) and Bronto parses and flattens them into searchable fields automatically — no parser needed. **Public zone query logs → [CloudWatch Log Forwarder](./aws-client-cloudwatch).** Public hosted-zone query logging can only be written to CloudWatch Logs; the Bronto forwarder Lambda subscribes to the resulting log group. Public query-log records are space-delimited, not JSON. If you route them to Firehose via a CloudWatch Logs subscription filter, Bronto stores each line raw and a [custom parser](/core-features/custom-parser) is required to extract fields. See [Formats requiring a custom parser](./aws-firehose-logs#formats-requiring-a-custom-parser). ## Alternatives * [**S3 Log Forwarder**](./aws-client-s3) — for Resolver query logs delivered to an S3 bucket. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon Route 53 — logging DNS queries](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/query-logs.html) # Amazon SES Sending Events Source: https://docs.bronto.io/integrations/aws-ses Send Amazon SES delivery, bounce, complaint, reject, open, and click events to Bronto to monitor email deliverability and investigate send failures. Amazon SES emits sending-activity events — deliveries, bounces, complaints, rejects, rendering failures, opens, and clicks — through a configurable event destination on each configuration set. SES supports CloudWatch, Kinesis Data Firehose, Amazon SNS, EventBridge, and Pinpoint as event destinations. ## Recommended method [**Kinesis Firehose**](./aws-firehose-logs) — add a **Kinesis Data Firehose event destination** to the configuration set and point it at Bronto. This delivers the full event JSON — `mail{}`, the event-specific object (`delivery{}`, `bounce{}`, `open{}`, `click{}`, …), and nested `tags{}` — which Bronto parses and flattens into searchable fields automatically. SES's **CloudWatch** event destination publishes CloudWatch **metrics** (counts of sends, bounces, etc.), not a log group containing the event bodies. To capture the event JSON itself, use the Firehose event destination. ## Alternatives For metric-level monitoring only, the configuration set can publish to a CloudWatch event destination, but this does not produce the per-event JSON that Bronto ingests. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [Amazon SES — monitor sending activity](https://docs.aws.amazon.com/ses/latest/dg/monitor-sending-activity.html) # AWS Step Functions Execution Logs Source: https://docs.bronto.io/integrations/aws-step-functions Ingest AWS Step Functions execution history — state transitions, input/output payloads, errors, and durations — into Bronto to debug workflow failures at scale. AWS Step Functions can emit execution-level logs — state transitions, input and output payloads, errors, and per-state durations — to CloudWatch Log Groups. State machines also publish status-change events to EventBridge. ## Recommended method [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — enable logging on each state machine with a destination Log Group, and the Bronto forwarder Lambda subscribes to it. ## Alternatives * [**EventBridge API Destinations**](./aws-eventbridge) — for execution status-change events (started, succeeded, failed, timed out) when full step-by-step detail isn't required. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [AWS Step Functions — logging with CloudWatch Logs](https://docs.aws.amazon.com/step-functions/latest/dg/cw-logs.html) # VPC Flow Logs Source: https://docs.bronto.io/integrations/aws-vpc-flow-logs Ingest VPC Flow Logs — IP traffic records for network interfaces in your VPC, useful for security analysis, network diagnostics, and compliance. VPC Flow Logs capture IP traffic to and from network interfaces in your VPC — source and destination IPs and ports, protocol, packet and byte counts, and accept / reject status. They underpin security analysis, network diagnostics, and compliance use cases. ## Recommended method [**S3 Log Forwarder**](./aws-client-s3) — configure flow logs at the VPC, subnet, or network interface level with S3 as the destination, then point the Bronto forwarder Lambda at the bucket. ## Alternatives * [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — when flow logs are already published to a CloudWatch Log Group. * [**Kinesis Firehose**](./aws-firehose-logs) — for very high traffic volumes. Flow logs can be delivered directly to Firehose (or via a CloudWatch Logs subscription filter). The default v2 flow-log record is a **space-delimited positional line** (`version account-id interface-id srcaddr dstaddr srcport dstport protocol packets bytes start end action log-status`). Bronto stores it raw and does **not** extract these fields automatically. Build a [custom parser](/core-features/custom-parser) pinned to the exact field order configured on the flow log. See [Formats requiring a custom parser](./aws-firehose-logs#formats-requiring-a-custom-parser). See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [VPC Flow Logs](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html) # AWS WAF Logs Source: https://docs.bronto.io/integrations/aws-waf Ingest AWS WAF web ACL traffic logs — allowed, blocked, and counted requests with rule match details — into Bronto for security monitoring and threat hunting. AWS WAF can log every request that hits a web ACL — including the rule that matched, the action taken (allow, block, count, captcha), the source IP, and the request headers. The logs are the foundation for security analytics and rule tuning. ## Recommended method [**S3 Log Forwarder**](./aws-client-s3) — configure logging on each web ACL with an S3 destination, then point the Bronto forwarder Lambda at the bucket. ## Alternatives * [**Kinesis Firehose**](./aws-firehose-logs) — for very high request volumes. WAF delivers logs directly to Firehose as native JSON, so Bronto flattens them into searchable fields automatically (`action`, `httpRequest.clientIp`, `terminatingRuleId`, …) — no parser needed. AWS requires the Firehose delivery stream name to start with `aws-waf-logs-` before WAF will allow it as a logging destination. * [**CloudWatch Log Forwarder**](./aws-client-cloudwatch) — when logs are routed to a CloudWatch Log Group instead. See [Ingesting AWS Data into Bronto](./aws-overview) for the full service-to-method mapping. ## References * [AWS WAF — logging](https://docs.aws.amazon.com/waf/latest/developerguide/logging.html) # Azure Container Instances Telemetry Source: https://docs.bronto.io/integrations/azure-aci Choose the right ingestion path for container stdout logs, metrics, and traces from Azure Container Instances, using an OpenTelemetry Collector sidecar. Azure Container Instances emits container `stdout` / `stderr` logs and — when your applications are instrumented with OpenTelemetry — metrics and distributed traces. Containers in the same container group share a network namespace, so a collector can run alongside your app as a sidecar. ## Recommended method [**Self-Managed OTel Collector**](./azure-otel#self-managed-opentelemetry-collector) — run the Collector as a sidecar. A same-group application normally uses `localhost:4317` for OTLP/gRPC or `localhost:4318` for OTLP/HTTP; use the actual receiver address and security settings when your configuration differs. The Collector forwards all three signals to Bronto. See [Ingesting Azure Data into Bronto](./azure-overview) for the full service-to-method mapping. ## References * [Retrieve container logs and events in Azure Container Instances](https://learn.microsoft.com/en-us/azure/container-instances/container-instances-log-analytics) # Azure Kubernetes Service Telemetry Source: https://docs.bronto.io/integrations/azure-aks Choose the right ingestion path for pod logs, kubelet metrics, control plane logs, and traces from Azure Kubernetes Service with a Collector DaemonSet. AKS workloads emit pod logs and application telemetry, while the kubelet exposes node, pod, container, and volume metrics. Control-plane logs are exported through Azure Monitor diagnostic settings. ## Recommended method [**Self-Managed OTel Collector**](./azure-otel#self-managed-opentelemetry-collector) — deploy the Collector as a DaemonSet to collect pod logs, kubelet metrics, and application telemetry. See [Kubernetes logs and metrics](/integrations/kubernetes) for the Helm preset and RBAC requirements. For **Windows node pools**, run the Collector DaemonSet on the Windows nodes (the `opentelemetry-collector-contrib` image ships the Windows receivers) to collect Windows Event Log and IIS logs, plus Windows performance-counter and IIS metrics — see [Collecting Windows OS Logs and Metrics](./azure-windows-logs). ## Alternatives * [**Azure Event Hub Forwarder**](./azure-client) — required path for AKS control plane / diagnostic logs, which are exported through Azure Monitor diagnostic settings to an Event Hub. See [Ingesting Azure Data into Bronto](./azure-overview) for the full service-to-method mapping. ## References * [Monitor Azure Kubernetes Service](https://learn.microsoft.com/en-us/azure/aks/monitor-aks) # Azure App Service Telemetry Source: https://docs.bronto.io/integrations/azure-app-service Choose the right ingestion path for application logs, web server logs, platform diagnostics, and traces from Azure App Service with OpenTelemetry. Azure App Service emits application logs (your code's `stdout` output), HTTP / web server logs, and platform diagnostic logs, and — when your application is instrumented — distributed traces. App Service does not run a node-level agent, so application telemetry is best emitted directly from the app. ## Recommended method [**OpenTelemetry SDK**](/opentelemetry/overview) — instrument the application and send logs, metrics, and traces to Bronto, either directly or through a [Collector](./azure-otel#self-managed-opentelemetry-collector). ## Alternatives * [**Azure Monitor OpenTelemetry Distro**](./azure-monitor-otel-distro) — if you already use Application Insights, you can forward the same standard OTLP logs, metrics, and traces to Bronto. * [**Azure Event Hub Forwarder**](./azure-client) — for App Service platform / diagnostic logs exported through Azure Monitor diagnostic settings. See [Ingesting Azure Data into Bronto](./azure-overview) for the full service-to-method mapping. ## References * [Enable diagnostics logging for apps in Azure App Service](https://learn.microsoft.com/en-us/azure/app-service/troubleshoot-diagnostic-logs) # Azure Event Hub Forwarder Source: https://docs.bronto.io/integrations/azure-client Forward Azure logs to Bronto using Azure Event Hub and the Bronto log forwarder to centralize platform, diagnostic, and application telemetry. ## Bronto Log Forwarder for Azure ### How it works The Bronto log forwarder for Azure is built around a Function App that collects log data from Azure Event Hub and sends it to Bronto. ### Steps Set Up Event Hub Infrastructure Using Our Terraform Module: This will automatically create and configure relevant resources (e.g. Event Hub, Function App, etc), using the details from the configurations below. The creation of an Event Hub is optional with the module, to accommodate for cases where such an Event Hub would already be in place. Stream Events from Azure services or resources to Event Hub: Using the Diagnostic setting, you can configure each Azure resource to stream certain events to an event hub: [Azure steps to stream logs to an event hub.](https://learn.microsoft.com/en-us/entra/identity/monitoring-health/howto-stream-logs-to-event-hub?tabs=splunk#stream-logs-to-an-event-hub) Verifying Log Data in Bronto: Once the relevant data is generated in Azure and streamed to Event Hub, shortly log events will appear in the Bronto UI. These logs will be displayed in the appropriate datasets which will be automatically created at ingestion time. ### Resources For Terraform users, Bronto offers a module that simplifies the setup of the forwarding Function App and its associated Event Hub resources. You can access the module source at [this URL](https://releases.bronto.io/integrations/azure/terraform/1.0.1/brontoForwarder.zip). Below is an example of how to use the Terraform module for Bronto log forwarding. This example assumes that a Resource Group, Event Hub, and all necessary resources for deploying the Bronto Function App will be created. Ensure that you replace `` with your Bronto account region (EU, US). ```javascript theme={"dark"} module "forwarder" { source = "https://releases.bronto.io/integrations/azure/terraform/latest/brontoForwarder.zip" location = "canadacentral" resource_group = { create = true name = "brontoforwarder" } eventhub = { create = true name = "brontoforwarder" namespace = { name = "brontoforwarder" sku = "Basic" } retention_days = 1 } forwarder = { name = "brontoforwarder" service_plan_type = "Y1" storage_account = { name = "brontoforwarder" replication_type = "LRS" tier = "Standard" } bronto_config = { ingestion_endpoint = "https://ingestion..bronto.io" ingestion_key = data.aws_kms_secrets.secrets.plaintext["bronto_ingestion_key"] default_collection = "azure" } } } ``` If an Event Hub for receiving log data is already configured in your environment, you can create only the resources related to the forwarding Bronto Function App using a configuration like the one below (not `create = false`): ```javascript theme={"dark"} module "forwarder" { source = "https://releases.bronto.io/integrations/azure/terraform/latest/brontoForwarder.zip" location = "canadacentral" resource_group = { create = false name = "brontoforwarder" } eventhub = { create = false name = var.eventhub.name namespace = var.eventhub.namespace } forwarder = { name = "brontoforwarder" service_plan_type = "Y1" storage_account = { name = "brontoforwarder" replication_type = "LRS" tier = "Standard" } bronto_config = { ingestion_endpoint = "https://ingestion..bronto.io" ingestion_key = data.aws_kms_secrets.secrets.plaintext["bronto_ingestion_key"] default_collection = "azure" } } } ``` For those not using Terraform, the Function App forwarder artifact is available for download at [this URL](https://releases.bronto.io/integrations/azure/forwarders/eventhub/latest/brontoForwarder.zip). ### Streaming from a Log Analytics workspace If your logs are already collected in an Azure Monitor Log Analytics workspace, you don't need to reconfigure each source's diagnostic settings. Use the workspace's [Data Export](https://learn.microsoft.com/en-us/azure/azure-monitor/logs/logs-data-export) feature to continuously stream selected tables to the same Event Hub the forwarder consumes: 1. Create a Data Export rule on the Log Analytics workspace. 2. Select the tables to export (for example, `AzureActivity` or `SigninLogs`). 3. Set the destination to the Event Hub namespace used by the Bronto forwarder. From there, the forwarder picks up the events exactly as it does for logs streamed directly via diagnostic settings. This is useful when a source can only write to Log Analytics, or when you already centralize there and want Bronto to receive a copy. ### Troubleshooting ### Ensure and verify log events are being sent to the event hub. * Navigate to Event Hubs on Azure. * Search for the event hub created earlier. Here you will see an overview table for this event hub and metrics on messages being received broken down by incoming and and outgoing messages. * If this is empty please ensure that events are being streamed to the correct event hub. * If metrics show that data goes in and out of event hub and yet you do not see data in Bronto, please check your ingestion endpoint and region is correct (US, EU) and that your Bronto API key set as environment variables on the Function App are correct. ### Notes on event categorisation When ingesting log data, Bronto automatically assigns it to a collection and dataset based on the information received with the payload. Azure logs forwarded through the Bronto integration are, by default, assigned to the unknown\_service dataset within the azure collection. However, the following log types are automatically assigned to more specific collections and datasets: * Activity Logs * Function App Logs * Entra ID Logs * Network Security Perimeter Logs If you are forwarding a log type that is not listed above and would like it assigned to a specific collection and dataset, please contact us at [support@bronto.io](mailto:support@bronto.io). # Azure Container Apps Telemetry Source: https://docs.bronto.io/integrations/azure-container-apps Choose the right ingestion path for console logs, system logs, metrics, and traces from Azure Container Apps — a Collector container app or the OTel SDK. Azure Container Apps emits console and system logs. Instrumented applications can also emit OTLP metrics and traces. ## Recommended method [**Self-Managed OTel Collector**](./azure-otel#self-managed-opentelemetry-collector) — run the Collector as its own container app and have applications export logs, metrics, and traces to it, or export directly with the [OpenTelemetry SDK](/opentelemetry/overview). The Container Apps environment's built-in managed OpenTelemetry agent exports only over OTLP/gRPC, which Bronto's ingestion endpoint does not accept — so it can't deliver to Bronto directly. Use a Collector container or direct SDK export instead. ## Alternatives * [**Azure Event Hub Forwarder**](./azure-client) — for Container Apps platform / diagnostic logs exported through Azure Monitor diagnostic settings. See [Ingesting Azure Data into Bronto](./azure-overview) for the full service-to-method mapping. ## References * [Collect and read OpenTelemetry data in Azure Container Apps](https://learn.microsoft.com/en-us/azure/container-apps/opentelemetry-agents) # Azure Functions Telemetry Source: https://docs.bronto.io/integrations/azure-functions Choose the right ingestion path for function execution logs, host logs, metrics, and distributed traces from Azure Functions — the OTel SDK or a Collector. Azure Functions emits function execution logs (your code's output), host logs, and — when instrumented — distributed traces. The right ingestion path depends on whether you want application telemetry emitted directly from the function or the Function App's platform logs. ## Recommended method [**OpenTelemetry SDK**](/opentelemetry/overview) — instrument the function and send logs, metrics, and traces to Bronto, either directly or through a [Collector](./azure-otel#self-managed-opentelemetry-collector). ## Alternatives * [**Azure Monitor OpenTelemetry Distro**](./azure-monitor-otel-distro) — if you already use Application Insights, you can forward the same standard OTLP logs, metrics, and traces to Bronto. * [**Azure Event Hub Forwarder**](./azure-client) — Function App logs streamed through Azure Monitor diagnostic settings are automatically assigned to a dedicated collection and dataset by the forwarder. See [Ingesting Azure Data into Bronto](./azure-overview) for the full service-to-method mapping. ## References * [Use OpenTelemetry with Azure Functions](https://learn.microsoft.com/en-us/azure/azure-functions/opentelemetry-howto) # Azure Monitor OpenTelemetry Distro Source: https://docs.bronto.io/integrations/azure-monitor-otel-distro Forward logs, metrics, and traces to Bronto with Microsoft's Azure Monitor OpenTelemetry Distro when you already use Application Insights. The [Azure Monitor OpenTelemetry Distro](https://learn.microsoft.com/en-us/azure/azure-monitor/app/opentelemetry-enable) is Microsoft's distribution of the OpenTelemetry SDK for .NET, Java, Node.js, and Python. It bundles auto-instrumentation and is a convenient way to instrument applications on Azure compute platforms such as App Service, Functions, AKS, and VMs. The Distro is built around the Azure Monitor exporter, so it always sends telemetry to Azure Monitor / Application Insights. Because it is built on the standard OpenTelemetry SDK, you can add an OTLP exporter to forward the same logs, metrics, and traces to Bronto as well. This is a good fit if you already use Application Insights and want the same data in Bronto. If you only need data in Bronto, a [self-managed OpenTelemetry Collector](./azure-otel#self-managed-opentelemetry-collector) or the vendor-neutral [OpenTelemetry SDK](/opentelemetry/overview) sends directly to Bronto without also routing through Azure Monitor. ## How it compares to standard OpenTelemetry The Distro is not a separate agent — it is the upstream OpenTelemetry SDK plus Microsoft defaults: bundled auto-instrumentation, automatic Azure resource attributes, an Application Insights-aware sampler, and an always-on Azure Monitor exporter. Everything it emits is standard OpenTelemetry data, so anything you can capture with the Distro you can also capture with the plain SDK or a [Collector](./azure-otel#self-managed-opentelemetry-collector). Two things matter when forwarding to Bronto: * **The Azure Monitor leg can't be removed.** The Distro is built around the Azure Monitor exporter, so it always ships to Application Insights; adding an OTLP exporter sends the *same* telemetry to Bronto as well, so you pay on both sides. If you only want Bronto, use a Collector or the plain SDK. * **Some features are Azure-only.** Live Metrics, Statsbeat, and the Profiler are proprietary to Azure Monitor and have no OTLP equivalent, so they are not forwarded to Bronto. Standard OTLP logs, metrics, and traces are. ## Adding Bronto as a destination Add an OTLP exporter pointing at Bronto. The simplest approach is the standard OpenTelemetry environment variables, which the Distro respects for its OTLP exporter: ```bash theme={"dark"} OTEL_EXPORTER_OTLP_ENDPOINT=https://ingestion..bronto.io OTEL_EXPORTER_OTLP_HEADERS=x-bronto-api-key= OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf ``` Replace `` with `eu` or `us` and `` with your Bronto API key. See the [Bronto ingestion endpoints](./azure-otel#bronto-ingestion-endpoints) for the full endpoint list. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). You can also add the OTLP exporter in code (for example, an additional span processor in Node.js or `AddOtlpExporter()` in .NET); see Microsoft's [OpenTelemetry configuration guide](https://learn.microsoft.com/en-us/azure/azure-monitor/app/opentelemetry-configuration) for per-language examples. Microsoft does not officially support the OTLP exporter or third-party backends downstream of the Azure Monitor Distro. ## Sending to both Azure Monitor and Bronto with a Collector If your goal is to land data in **both** Application Insights and Bronto, a standard OpenTelemetry Collector can fan out to both without the Distro — and it stays fully supported upstream. Point your applications' OTLP export at the Collector and configure two exporters: the contrib [`azuremonitor`](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/azuremonitorexporter) exporter for Application Insights and `otlphttp` for Bronto. ```yaml theme={"dark"} receivers: otlp: protocols: http: endpoint: 0.0.0.0:4318 processors: batch: resourcedetection/azure: detectors: [env, azure] # use [env, aks] on AKS; adds Azure resource attributes exporters: azuremonitor: connection_string: "${APPLICATIONINSIGHTS_CONNECTION_STRING}" otlphttp/bronto: logs_endpoint: "https://ingestion..bronto.io/v1/logs" metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" traces_endpoint: "https://ingestion..bronto.io/v1/traces" compression: gzip headers: x-bronto-api-key: service: pipelines: traces: receivers: [otlp] processors: [resourcedetection/azure, batch] exporters: [azuremonitor, otlphttp/bronto] logs: receivers: [otlp] processors: [resourcedetection/azure, batch] exporters: [azuremonitor, otlphttp/bronto] metrics: receivers: [otlp] processors: [resourcedetection/azure, batch] exporters: [azuremonitor, otlphttp/bronto] ``` This keeps your applications on vendor-neutral OTLP and moves the dual-destination routing into the Collector, which also adds batching, compression, and retries. The `resourcedetection` processor adds the same Azure resource attributes (VM, App Service, or AKS metadata) that the Distro would populate automatically. ## Resource identity and log routing in Bronto Set the `service.name` and `service.namespace` resource attributes to identify the source across all three signals. For **logs only**, Bronto also maps them to the dataset and collection — see [Data Organization](/Search-and-Visualize/Partitions). Metrics and traces are not stored in datasets or collections; they appear in the Metric Explorer and Explore Traces. These are the same resource attributes the Distro already uses for Application Insights, so no Bronto-specific attributes are needed beyond the OTLP exporter. *** For assistance or questions, contact [support@bronto.io](mailto:support@bronto.io). # OpenTelemetry on Azure Source: https://docs.bronto.io/integrations/azure-otel Send application logs, metrics, and traces from Azure to Bronto using a self-managed OpenTelemetry Collector or the OpenTelemetry SDK. Bronto ingests OpenTelemetry **logs, metrics, and traces** over OTLP/HTTP. On Azure, the recommended path is a self-managed OpenTelemetry Collector, which sends data straight to Bronto with full control over routing and processing. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). ## Choosing an Approach | Approach | Best for | Notes | | - | - | - | | [Self-managed OTel Collector](#self-managed-opentelemetry-collector) **(recommended)** | AKS, VMs, Container Instances, Container Apps | Sends logs, metrics, and traces directly to Bronto with full control over processing, routing, and fan-out. | | [OpenTelemetry SDK](/opentelemetry/overview) | Any runtime (App Service, Functions, etc.) | The vendor-neutral OpenTelemetry SDK and auto-instrumentation, exporting OTLP directly to Bronto. | | [Azure Monitor OpenTelemetry Distro](./azure-monitor-otel-distro) | Teams already using Application Insights | Microsoft's SDK distro — a convenient option if you already run Application Insights and want to forward the same data to Bronto. See the [dedicated page](./azure-monitor-otel-distro). | *** ## Bronto Ingestion Endpoints | Signal | EU Region | US Region | | - | - | - | | Logs | `https://ingestion.eu.bronto.io/v1/logs` | `https://ingestion.us.bronto.io/v1/logs` | | Metrics | `https://ingestion.eu.bronto.io/v1/metrics` | `https://ingestion.us.bronto.io/v1/metrics` | | Traces | `https://ingestion.eu.bronto.io/v1/traces` | `https://ingestion.us.bronto.io/v1/traces` | The `/v1/logs`, `/v1/metrics`, and `/v1/traces` endpoints accept **OTLP protobuf over HTTP only**. Exponential histograms are not supported. All requests require the header: ``` x-bronto-api-key: ``` See [API Keys](/Account-Management/API-Keys) for how to generate a key. *** ## Self-Managed OpenTelemetry Collector Running your own OpenTelemetry Collector is the recommended approach: it sends logs, metrics, and traces straight to Bronto, without routing your data through any other vendor, and gives you: * **Full configuration control** — custom processors, attribute transformation, or sampling rules * **Fan-out** — forwarding the same telemetry to multiple backends simultaneously * **Existing OTel infrastructure** — you already operate a collector fleet and want to add Bronto as an exporter * **Advanced log routing** — sending logs from different types or services to different Bronto datasets or collections Application logs, metrics, and traces can be sent directly to Bronto's ingestion endpoints, but routing through a Collector is strongly recommended. The Collector handles retries, batching, and compression. ### Supported sources A self-managed Collector can run anywhere you control compute, and supports any source that has an OpenTelemetry receiver: | Service / Source | Data types | | - | - | | Azure Virtual Machines / VM Scale Sets | Application logs, metrics, and traces | | Azure Kubernetes Service (AKS) | Application logs, metrics, and traces (DaemonSet or Deployment) | | Azure Container Apps | Application logs, metrics, and traces (Collector container) | | Azure Container Instances (ACI) | Application logs, metrics, and traces (sidecar container) | | Any Azure workload reachable from the Collector | Logs, metrics, and traces via OTLP and other [OTel receivers](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver) | The Collector forwards only what it receives — deploying it does not automatically collect your logs. If you aren't seeing all the logs you expect: * **Application logs, metrics, and traces** require instrumenting your app with the [OpenTelemetry SDK](/opentelemetry/overview), or tailing its log files with the `filelog` receiver. * **Azure platform and diagnostic logs** (resource logs, activity logs) are **not** collected by the Collector — they are exported through Azure Monitor diagnostic settings via the [Event Hub Forwarder](./azure-client). See [Ingesting Azure Data into Bronto](./azure-overview) for the full per-service source-to-method mapping, and the per-service pages — [AKS](./azure-aks), [Container Apps](./azure-container-apps), [Container Instances](./azure-aci), [App Service](./azure-app-service), [Functions](./azure-functions), [Virtual Machines](./azure-vms) — for what each service emits and how. ### Collector configuration The core Bronto exporter configuration is the same regardless of how you deploy the collector on Azure. For full installation instructions and parameter reference, see the [OpenTelemetry Collector guide](/agent-setup/open-telemetry). The minimal configuration exports logs, metrics, and traces to Bronto: ```yaml theme={"dark"} receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: exporters: otlphttp/bronto: logs_endpoint: "https://ingestion..bronto.io/v1/logs" metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" traces_endpoint: "https://ingestion..bronto.io/v1/traces" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] metrics: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] traces: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] ``` Replace `` with `eu` or `us` and `` with your Bronto API key. ### Deployment options on Azure #### Azure Kubernetes Service (AKS) Deploy as a DaemonSet (one collector per node) for node-level log collection, or as a Deployment behind a ClusterIP service for centralised collection. The simplest path is the [OpenTelemetry Helm chart](https://github.com/open-telemetry/opentelemetry-helm-charts/tree/main/charts/opentelemetry-collector): ```bash theme={"dark"} helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts helm install otel-collector open-telemetry/opentelemetry-collector \ --values values.yaml ``` Add the `k8sattributes` processor to enrich logs, metrics, and traces with pod, namespace, and node metadata. See the [OpenTelemetry Collector guide](/agent-setup/open-telemetry#kubernetes) for a complete `values.yaml` example. #### Azure Virtual Machines / VM Scale Sets Install the OpenTelemetry Collector directly on your VMs following the [official installation guide](https://opentelemetry.io/docs/collector/installation/). Place your config at `/etc/otel/config.yaml` and run the collector as a systemd service. For VM Scale Sets, bake the collector into your image or install it via a custom-script extension or cloud-init so every instance starts the collector on boot. #### Azure Container Apps Run the OpenTelemetry Collector as its own container app and have your other apps export OTLP to it; the Collector forwards logs, metrics, and traces to Bronto over OTLP/HTTP. Alternatively, instrument each app with the [OpenTelemetry SDK](/opentelemetry/overview) to export to Bronto directly. The Container Apps environment's built-in managed OpenTelemetry agent exports only over OTLP/gRPC, which Bronto's ingestion endpoint does not accept — so it can't deliver to Bronto directly. Use a Collector container or direct SDK export instead. #### Azure Container Instances (ACI) Run the collector as a sidecar container within the same container group as your application. Both containers share the group's network namespace, so the usual defaults are `localhost:4317` for OTLP/gRPC and `localhost:4318` for OTLP/HTTP. Replace them when your receiver uses different port, protocol, or TLS settings. Use the standard `otel/opentelemetry-collector-contrib` image and provide your config via a mounted Azure Files share or a secret volume. ### Collecting from Windows hosts Windows workloads are common on Azure — VMs and VM Scale Sets, App Service on Windows plans, and Windows node pools on AKS. Windows hosts produce two distinct kinds of logs: **Windows Event Log** entries (collected with the `windowseventlog` receiver) and **file-based logs** such as IIS and SQL Server (collected with the `filelog` receiver). The same Collector you run for Linux workloads — including as an AKS DaemonSet on Windows nodes — can collect both. See [Collecting Windows OS Logs and Metrics](./azure-windows-logs) for the receiver configuration, the channels worth collecting, XPath filtering for noisy channels, Windows `filelog` gotchas (encoding, multi-line stack traces), and installing the Collector as a Windows service. *** ## Azure Monitor OpenTelemetry Distro If you already use Microsoft's [Azure Monitor OpenTelemetry Distro](./azure-monitor-otel-distro) with Application Insights, you can also forward the same logs, metrics, and traces to Bronto by adding an OTLP exporter. See the [dedicated page](./azure-monitor-otel-distro) for details. *** ## Log Data Organization OpenTelemetry resource attributes provide shared identity across logs, metrics, and traces. For **logs only**, Bronto maps `service.name` to a **Dataset** and `service.namespace` to a **Collection**. Metrics and traces are not stored in datasets or collections; view them in the [Metric Explorer](/metrics/explore-metrics) and [Explore Traces](/tracing/explore-traces). Set these as resource attributes in your SDK or collector config: ```yaml theme={"dark"} processors: resource: attributes: - key: service.name value: action: upsert - key: service.namespace value: action: upsert ``` You can also override **log routing** on a logs exporter using HTTP headers, which is useful when one collector ships logs to multiple datasets: | Header | Description | | - | - | | `x-bronto-dataset` | Overrides `service.name` for the log dataset | | `x-bronto-collection` | Overrides `service.namespace` for the log collection | | `x-bronto-tags` | Comma-separated tags to attach to the log dataset | ```yaml theme={"dark"} exporters: otlphttp/brontologs: logs_endpoint: https://ingestion..bronto.io/v1/logs headers: x-bronto-api-key: x-bronto-dataset: x-bronto-collection: x-bronto-tags: env=prod,team=platform ``` For Kubernetes logs, set `x-bronto-collection` to your cluster name (e.g. `cluster1-prod-eu-west-1`) to identify the source cluster in Bronto. *** For assistance or questions, contact [support@bronto.io](mailto:support@bronto.io). # Ingesting Azure Data into Bronto Source: https://docs.bronto.io/integrations/azure-overview An overview of the available methods for sending Azure log and trace data to Bronto, with guidance on choosing the right approach. ## Overview Bronto supports several methods for ingesting data from Azure environments. The right choice depends on where your telemetry originates, your infrastructure preferences, and cost constraints. Bronto ingests OpenTelemetry **logs, metrics, and traces**. Broadly, Azure telemetry falls into two categories: * **Platform, diagnostic, and activity logs** — emitted by Azure services through diagnostic settings. These are streamed to Bronto via the [Azure Event Hub Forwarder](./azure-client). * **Application logs, metrics, and traces** — emitted by your own workloads. Send these to Bronto using [OpenTelemetry on Azure](./azure-otel). *** ## Service-to-Method Mapping Different Azure services suit different ingestion methods. The recommended method is the simplest path that gets the data into Bronto; alternatives may be preferable depending on your existing infrastructure or cost constraints. Each service name in the table below links to a per-source landing page with a short summary of what the service emits and the configuration entry points for that data. Where the OpenTelemetry SDK supports your runtime, prefer OTel-based instrumentation — it sends logs, metrics, and traces through one Collector and gives you consistent resource identity. [OpenTelemetry on Azure](./azure-otel) covers AKS, Container Apps, Container Instances, VMs, App Service, and Functions. | Azure Service | Recommended Method | Alternatives | | - | - | - | | [Azure Virtual Machines / VM Scale Sets](./azure-vms) | [OTel Collector](./azure-otel#self-managed-opentelemetry-collector) | [Azure Monitor Distro](./azure-monitor-otel-distro), [Event Hub Forwarder](./azure-client) (diagnostic logs) | | [Azure Kubernetes Service (AKS)](./azure-aks) | [OTel Collector](./azure-otel#self-managed-opentelemetry-collector) | [Azure Monitor Distro](./azure-monitor-otel-distro), [Event Hub Forwarder](./azure-client) (control plane / diagnostic logs) | | [Azure Container Apps](./azure-container-apps) | [OTel Collector](./azure-otel#self-managed-opentelemetry-collector) (Collector container) / [OTel SDK](/opentelemetry/overview) | [Event Hub Forwarder](./azure-client) (diagnostic logs) | | [Azure Container Instances (ACI)](./azure-aci) | [OTel Collector](./azure-otel#self-managed-opentelemetry-collector) (sidecar) | — | | [Azure App Service](./azure-app-service) | [OTel SDK](/opentelemetry/overview) | [Azure Monitor Distro](./azure-monitor-otel-distro), [Event Hub Forwarder](./azure-client) (diagnostic logs) | | [Azure Functions](./azure-functions) | [OTel SDK](/opentelemetry/overview) | [Azure Monitor Distro](./azure-monitor-otel-distro), [Event Hub Forwarder](./azure-client) (Function App logs) | | Microsoft Foundry (agent / LLM telemetry) | [OTel SDK](/ai-features/microsoft-foundry) | [OTel Collector](./azure-otel#self-managed-opentelemetry-collector) | | Azure SQL Database | [Event Hub Forwarder](./azure-client) (diagnostic / audit logs) | — | | Azure Monitor / Activity Logs | [Event Hub Forwarder](./azure-client) | — | | Microsoft Entra ID (sign-in / audit logs) | [Event Hub Forwarder](./azure-client) | — | | Network Security Perimeter Logs | [Event Hub Forwarder](./azure-client) | — | *** ## Ingestion Methods Bronto supports the following Azure ingestion methods: * [Azure Event Hub Forwarder](./azure-client) — A Bronto Function App subscribes to an Event Hub and forwards platform, diagnostic, and activity logs streamed to it via diagnostic settings. It can also receive logs re-exported from a Log Analytics workspace via [Data Export](./azure-client#streaming-from-a-log-analytics-workspace). * [OpenTelemetry on Azure](./azure-otel) — Application logs, metrics, and traces via a self-managed OpenTelemetry Collector or the OpenTelemetry SDK. * [Azure Monitor OpenTelemetry Distro](./azure-monitor-otel-distro) — Microsoft's SDK distro; a convenient option for teams already using Application Insights who want to forward the same data to Bronto. * [Microsoft Foundry observability](/ai-features/microsoft-foundry) — Logs, metrics, and traces from Foundry apps and agents, including model calls, token usage, tool invocations, and multi-agent hierarchies. *** For assistance or questions, contact [support@bronto.io](mailto:support@bronto.io). # Azure Virtual Machines Telemetry Source: https://docs.bronto.io/integrations/azure-vms Choose the right ingestion path for system logs, application logs, host metrics, and distributed traces from Azure Virtual Machines and VM Scale Sets. Azure Virtual Machines and VM Scale Sets emit OS / system logs and application log files, and — when your applications are instrumented — metrics and distributed traces. Because you control the compute, a collector can run directly on the instance and also scrape host metrics. ## Recommended method [**Self-Managed OTel Collector**](./azure-otel#self-managed-opentelemetry-collector) — install the Collector as a systemd service or Windows service to collect host telemetry and accept application logs, metrics, and traces over OTLP. For VM Scale Sets, bake it into the image or install it through cloud-init or a custom-script extension. For **host metrics** — CPU, memory, disk, filesystem, and network — add the `hostmetrics` receiver; see [Host metrics with OpenTelemetry](/integrations/host-metrics). On **Windows** VMs, collect Windows Event Log channels (Application, System, Security) with the `windowseventlog` receiver and file-based logs such as IIS access logs with the `filelog` receiver. Windows performance counters, IIS, and SQL Server metrics have dedicated receivers — see [Collecting Windows OS Logs and Metrics](./azure-windows-logs). ## Alternatives * [**Azure Event Hub Forwarder**](./azure-client) — for VM platform / diagnostic logs exported through Azure Monitor diagnostic settings. See [Ingesting Azure Data into Bronto](./azure-overview) for the full service-to-method mapping. ## References * [Monitor virtual machines with Azure Monitor](https://learn.microsoft.com/en-us/azure/azure-monitor/vm/monitor-virtual-machine) # Collecting Windows OS Logs and Metrics Source: https://docs.bronto.io/integrations/azure-windows-logs Collect Windows Event Logs, IIS and SQL Server log files, and Windows performance-counter metrics with the OpenTelemetry Collector and ship them to Bronto. Windows hosts produce two distinct kinds of logs, and each needs a different OpenTelemetry receiver: * **Windows Event Log** — platform and service diagnostics written to the event log (visible in **Event Viewer**), collected with the `windowseventlog` receiver. * **File-based logs** — IIS access logs, SQL Server error logs, and custom application files on disk, collected with the `filelog` receiver. The same Collector can also send **metrics** — see [Metrics](#metrics) for Windows performance counters and the dedicated IIS and SQL Server receivers. The `otel/opentelemetry-collector-contrib` image and the Windows Collector binary include both receivers, so the same Collector you run for Linux workloads can collect Windows logs. Once the data reaches Bronto over OTLP it is ingested the same way regardless of the source OS. This applies to any Windows host you run a Collector on. On Azure that includes **VMs and VM Scale Sets**, **App Service on Windows plans**, and **Windows node pools on AKS** (where the Collector runs as a DaemonSet on the Windows nodes). These examples show only the receivers and how to wire them into a logs pipeline. They assume you already run an OpenTelemetry Collector with a Bronto exporter configured — see [OpenTelemetry on Azure](./azure-otel) or the [OpenTelemetry Collector guide](/agent-setup/open-telemetry) for the base setup, endpoints, and `service.name` / `service.namespace` routing. The `windowseventlog` receiver is Windows-only — it must run on a Windows host or in a Windows container. The `filelog` receiver works on any OS. ## Windows Event Log Most Windows platform and service diagnostics are written to the Windows Event Log, **not** to files on disk. Collect these with the [`windowseventlog` receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/windowseventlogreceiver), one receiver per channel: ```yaml theme={"dark"} receivers: windowseventlog/application: channel: Application windowseventlog/system: channel: System windowseventlog/security: channel: Security ``` `channel` accepts any event channel name, so you can scope collection to exactly the sources you care about. Channels commonly worth collecting on Windows hosts: | Channel | Captures | | - | - | | `Application` | Events from installed applications and services | | `System` | Events from Windows system components and drivers | | `Security` | Audit events — logon, privilege use, object access (high volume) | | `Setup` | Application install and servicing events | | `ForwardedEvents` | Events collected from other hosts via Windows Event Forwarding (WEF) | | `Microsoft-Windows-PowerShell/Operational` | PowerShell script-block and pipeline execution | | `Microsoft-Windows-Sysmon/Operational` | Sysmon process / network / file telemetry (if Sysmon is installed) | | `Microsoft-Windows-Windows Defender/Operational` | Microsoft Defender detections and scan results | On domain controllers, also collect the `Directory Service` and `DNS Server` channels alongside `Security` for Active Directory audit events. ### Filtering noisy channels High-volume channels — `Security` in particular — can dominate ingestion. Use the receiver's `query` option to collect only the events you need via an XPath expression, keeping volume and cost down before data leaves the host. Filter `Security` by Event ID: ```yaml theme={"dark"} receivers: windowseventlog/security: channel: Security query: | ``` (`4624` successful logon, `4625` failed logon, `4672` special privileges assigned.) For `Application` and `System`, filtering by severity is often more useful — `*[System[(Level=1 or Level=2 or Level=3)]]` keeps only Critical, Error, and Warning events. ## File-based logs Logs written to disk — IIS access logs, SQL Server error logs, custom application log files — are collected with the standard `filelog` receiver. On Windows, write `include` paths with forward slashes (or escaped backslashes): ```yaml theme={"dark"} receivers: filelog/app: include: - C:/logs/*.log # Some Windows apps and PowerShell transcripts write UTF-16, not UTF-8 encoding: utf-16le # Keep multi-line .NET exception stack traces together as one event multiline: line_start_pattern: '^\d{4}-\d{2}-\d{2}' filelog/iis: include: - C:/inetpub/logs/LogFiles/W3SVC*/*.log # IIS access logs (W3C) - C:/Windows/System32/LogFiles/HTTPERR/*.log # HTTP.sys connection errors filelog/sqlserver: include: - C:/Program Files/Microsoft SQL Server/MSSQL*/MSSQL/Log/ERRORLOG* ``` Two Windows-specific points to watch: * **Encoding** — IIS logs are UTF-8, but many Windows tools (PowerShell transcripts, some application logs) write UTF-16. Set `encoding: utf-16le` on those receivers or the text will be garbled. * **Multi-line events** — .NET exception stack traces span many lines. Without a `multiline.line_start_pattern`, each line is ingested as a separate event; the pattern above keeps a full stack trace as a single record. IIS writes access logs in W3C extended log format (space-delimited fields with a `#Fields:` header). Pair the `filelog` receiver with a parsing operator or the `transform` processor if you want those fields broken out into structured attributes — or ship the raw lines and use the [Bronto Custom Parser](/core-features/custom-parser), which has built-in IIS support. The `filelog` receiver only reads files on disk — it will **not** pick up Windows Event Log entries. If logs you expect are missing, confirm whether they are written to a file or to the Event Log (Event Viewer): the former needs `filelog`, the latter needs `windowseventlog`. Pointing `filelog` at logs that actually live in the Event Log is the most common cause of missing Windows logs. ## Metrics Bronto ingests OTLP metrics, so the same Collector can carry Windows metrics alongside the logs above. ### Host and OS metrics For CPU, memory, disk, filesystem, and network metrics, use the cross-platform `hostmetrics` receiver — it supports Windows as well as Linux and macOS. See [Host metrics with OpenTelemetry](/integrations/host-metrics) for the scraper list and full configuration. ### Windows performance counters For counters that `hostmetrics` does not expose — .NET CLR, ASP.NET, Microsoft Exchange, or any custom application counter — use the [`windows_perf_counters` receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/windowsperfcountersreceiver). You declare the metric to emit and the counters that feed it: ```yaml theme={"dark"} receivers: windows_perf_counters: collection_interval: 30s metrics: process.cpu.utilization: description: Percentage of processor time consumed by the process. unit: "%" gauge: perfcounters: - object: Process instances: ["*"] counters: - name: "% Processor Time" metric: process.cpu.utilization ``` The receiver type is `windows_perf_counters`. The older `windowsperfcounters` spelling is deprecated. The receiver is Windows-only and reads counters through the PDH interface, so a counter that is not installed on the host is skipped with a warning rather than failing startup. ### IIS metrics For IIS request rates, connections, queue depth, and uptime, use the dedicated [`iis` receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/iisreceiver) rather than hand-rolling counters. It reads the IIS performance counters for you: ```yaml theme={"dark"} receivers: iis: collection_interval: 30s ``` The `iis` receiver is Windows-only and is not available on Windows `arm64`. ### SQL Server metrics The [`sqlserver` receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/sqlserverreceiver) works two ways. On Windows it can read the SQL Server performance counters with no connection details — the Collector must run as **administrator** to see them all: ```yaml theme={"dark"} receivers: sqlserver: collection_interval: 30s ``` Or connect directly to the instance, which also works when the Collector runs off-host (for example against Azure SQL): ```yaml theme={"dark"} receivers: sqlserver: collection_interval: 30s server: sqlserver.internal port: 1433 username: password: ``` Direct connection requires `VIEW SERVER STATE` on SQL Server before 2022, or `VIEW SERVER PERFORMANCE STATE` on 2022 and later. All four of `server`, `port`, `username`, and `password` must be set to enable this mode. Bronto supports OTLP sums, gauges, summaries, and explicit histograms. Exponential histograms are not currently supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). ## Wiring into the pipeline Add the Windows receivers to the Collector's pipelines alongside your existing sources, exporting to your configured Bronto exporter: ```yaml theme={"dark"} service: pipelines: logs: receivers: [otlp, windowseventlog/application, windowseventlog/system, filelog/iis] processors: [batch] exporters: [otlphttp/bronto] metrics: receivers: [otlp, hostmetrics, windows_perf_counters, iis, sqlserver] processors: [batch] exporters: [otlphttp/bronto] ``` Include only the receivers you configured — `iis` and `sqlserver` are relevant only on hosts running those workloads. If your Bronto exporter is signal-specific (for example `otlphttp/brontologs` and `otlphttp/brontometrics`), reference the matching exporter in each pipeline. ## Installing the Collector on Windows Install the Collector from the `opentelemetry-collector-contrib` Windows **MSI** — which registers it as a Windows service automatically — or from the zip release. With the zip, register the service yourself so it starts on boot: ```powershell theme={"dark"} New-Service -Name otelcol-contrib ` -BinaryPathName '"C:\Program Files\otelcol-contrib\otelcol-contrib.exe" --config "C:\otel\config.yaml"' ` -StartupType Automatic Start-Service otelcol-contrib ``` For VM Scale Sets, install and register the service through a custom-script extension or in your image build so every instance starts the Collector on boot. *** For assistance or questions, contact [support@bronto.io](mailto:support@bronto.io). # Cloudflare Source: https://docs.bronto.io/integrations/cloudflare Forward Cloudflare HTTP request, firewall, and Workers logs to Bronto in near real time using Logpush for analysis of edge traffic and security events. This feature is only available with an enterprise plan or by subscribing to a paid workers plan. ## Bronto API Key First, an API key is required in order to be able to successfully ingest data into Bronto. To generate an API key in Bronto, please refer to the [API Keys documentation](/Account-Management/API-Keys). ## Method 1: UI-Based Setup (Recommended) The easiest way to set up Logpush to Bronto is through the Cloudflare Dashboard. Follow these steps: * Go to your Cloudflare dashboard * Navigate to `Analytics & Logs` > `Logpush` * Select `Create a Logpush job` * Select Destination > Http Destination * Enter the HTTP endpoint URL which is the Bronto ingestion URL, ensuring to replace the Region (EU, US), API Key ,and your Namespace and Service parameters: ``` https://ingestion.eu.bronto.io/?header_x-bronto-api-key=&service_namespace=&service_name= ``` * Follow the remaining prompts to complete the setup Once configured, you’ll see your Logpush job listed in the UI. ## Configuring Batch Size Our ingestion endpoints have a limit of 10MB per HTTP payload. Cloudflare allows users to configure the `max_upload_bytes` setting via their API. Because payloads from Cloudflare are compressed with GZIP, it is generally safe to set `max_upload_bytes` up to 20MB, as the compressed size will typically be reduced to less than 10MB. Recommended configuration based on log volume: * Set `max_upload_bytes` to 5MB for log volumes under 200GB/day * Set `max_upload_bytes` to 10MB for log volumes under 500GB/day * Set `max_upload_bytes` to 20MB for log volumes over 500GB/day See below for an example curl to set the `max_upload_bytes` to 10MB: ```bash Set max_upload_bytes theme={"dark"} curl -X PUT "https://api.cloudflare.com/client/v4/zones//logpush/jobs/" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ --data '{ "max_upload_bytes": 10000000, }' ``` For further details please visit the dedicated Cloudflare documentation [here](https://developers.cloudflare.com/logs/logpush/logpush-job/api-configuration/#max-upload-parameters). **Note:** Cloudflare can batch log events and only send them once the maximum batch size is reached, so some events may be delayed. ## Method 2: REST API Setup You can also manage Logpush jobs using Cloudflare’s REST API. The full API documentation is available [here](https://developers.cloudflare.com/logs/get-started/api-configuration/). ## Cloudflare API Key A Cloudflare API key is also required for the setup, a global API key can be used or alternatively a custom API token with Logs:Edit permissions can be created. Bronto will not see the Cloudflare API Key or Token. ## Cloudflare Logging Configuration Management of HTTP destinations is via a REST API, the full API docs can be found [here](https://developers.cloudflare.com/logs/get-started/api-configuration/). Once a new logging endpoint is created, it's visible in the Cloudflare UI under `Analytics & Logs` > `Logpush`. To create a new Logpush job to forward logs to Bronto, make the follow `curl` request: ```bash Create Logpush Job theme={"dark"} curl --request POST \ --url https://api.cloudflare.com/client/v4/accounts//logpush/jobs \ --header 'Content-Type: application/json' \ --header 'X-Auth-Email: ' \ --header 'X-Auth-Key: ' \ --data '{ "dataset": "workers_trace_events", "destination_conf": "https://ingestion.eu.bronto.io/?header_x-bronto-api-key=&service_namespace=&service_name=", "enabled": true, "output_options": { "field_delimiter": ",", "batch_prefix": "", "batch_suffix": "", "CVE-2021-44228": false, "field_names": [ "DispatchNamespace", "Entrypoint", "Event", "EventTimestampMs", "EventType", "Exceptions", "Logs", "Outcome", "ScriptName", "ScriptTags", "ScriptVersion" ], "output_type": "ndjson", "sample_rate": 1, "timestamp_format": "unixnano" } }' ``` To verify a Logpush job has been created, make the following `curl` request: ```bash View Logpush Jobs theme={"dark"} curl --request GET \ --url https://api.cloudflare.com/client/v4/accounts//logpush/jobs \ --header 'Content-Type: application/json' \ --header 'X-Auth-Email: ' \ --header 'X-Auth-Key: ' ``` # Docker container logs and metrics with OpenTelemetry Source: https://docs.bronto.io/integrations/docker Collect container logs and runtime metrics from Docker and Docker Compose with the OpenTelemetry Collector and forward them to Bronto. Collect logs and runtime metrics from Docker and Docker Compose with the OpenTelemetry Collector. The `filelog` receiver reads Docker's `json-file` logs, while `docker_stats` reads CPU, memory, network, block-I/O, and container-status metrics from the Docker API. ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * Docker using the default [`json-file` logging driver](https://docs.docker.com/engine/logging/configure/) (logs at `/var/lib/docker/containers/*/*-json.log`) * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) — run it as a container alongside your services ## Run the Collector Add the Collector to your `docker-compose.yml` and give it read access to Docker's container log directory and API socket: ```yaml docker-compose.yml theme={"dark"} services: otel-collector: image: otel/opentelemetry-collector-contrib:latest command: ["--config=/etc/otel/config.yaml"] volumes: - ./otel-config.yaml:/etc/otel/config.yaml:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro - /var/run/docker.sock:/var/run/docker.sock:ro ``` The Collector tails the container logs, unwraps Docker's JSON envelope, and ships to Bronto: ```yaml otel-config.yaml theme={"dark"} receivers: filelog/docker: include: - /var/lib/docker/containers/*/*-json.log operators: - type: json_parser resource: service.name: service.namespace: docker_stats: endpoint: unix:///var/run/docker.sock collection_interval: 30s processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: otlphttp/brontometrics: metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/docker] processors: [batch] exporters: [otlphttp/brontologs] metrics: receivers: [docker_stats] processors: [batch] exporters: [otlphttp/brontometrics] ``` Set `` to `eu` or `us`. For receiver options and the full measurement list, see the [Collector Contrib Docker Stats receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/dockerstatsreceiver). ## What you will see in Bronto Logs appear in Search. Docker's `json-file` driver wraps each line as `{"log": "...", "stream": "stdout|stderr", "time": "..."}`; the `json_parser` operator promotes those into fields. Runtime measurements appear in the Metric Explorer. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). This covers container logs and runtime metrics. To add distributed traces and per-route RED metrics for the applications in those containers, without changing them, see [Zero-code instrumentation with eBPF](/opentelemetry/ebpf). ## Troubleshooting * **No logs?** Confirm the driver is `json-file` (`docker inspect -f '{{.HostConfig.LogConfig.Type}}' `) and that the Collector mounts `/var/lib/docker/containers` read-only. * **No metrics?** Confirm the Collector mounts `/var/run/docker.sock` and its user can read the socket. * **Per-service datasets?** Run one Collector centrally with a `service.name` per environment, or route by container labels with an `attributes` processor. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit If you already run Fluent Bit, tail the container log files and forward them over HTTP. The `docker` multiline parser reassembles partial lines from the `json-file` driver: ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/lib/docker/containers/*/*-json.log multiline.parser docker tag docker [OUTPUT] name http match docker host ingestion..bronto.io port 443 tls on format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset header x-bronto-collection ``` Set **Format** to `json_lines`, not `json`. You can also point Docker's native [`fluentd` logging driver](https://docs.docker.com/engine/logging/configure/) at Fluent Bit. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit) for installation. # Docker build traces with BuildKit and OpenTelemetry Source: https://docs.bronto.io/integrations/docker-build Send Docker BuildKit build traces to Bronto over OTLP to see per-step durations, cache hits and misses, and where build time is spent. BuildKit — the builder behind `docker build` and `docker buildx` — is already instrumented with OpenTelemetry. It records a trace for every build with one span per Dockerfile step, and exports straight to Bronto over OTLP/HTTP, so no Collector is involved. To collect runtime logs from your running containers instead, see [Docker](./docker). ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * Docker Engine with Buildx (verified with Docker 29.6, Buildx v0.35, BuildKit v0.31) * A builder on the `docker-container` driver — the default `docker` driver runs BuildKit inside the Docker daemon, where these variables cannot be set ## See the trace locally BuildKit keeps a record of recent builds, so you can view a trace before configuring anything: ```bash theme={"dark"} docker buildx history trace ``` These records are local and short-lived. Exporting to Bronto turns them into build history you can query across every developer machine and CI runner. ## Configure the builder ```bash theme={"dark"} export OTEL_SERVICE_NAME= docker buildx create --name otel-builder --use \ --driver docker-container \ --driver-opt env.OTEL_TRACES_EXPORTER=otlp \ --driver-opt env.OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \ --driver-opt env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://ingestion..bronto.io/v1/traces \ --driver-opt env.OTEL_EXPORTER_OTLP_HEADERS=x-bronto-api-key= \ --driver-opt env.OTEL_SERVICE_NAME= docker buildx inspect --bootstrap ``` Set `` to `eu` or `us`. `service.name` identifies the builder in Explore Traces; it does not select or create a dataset. From here, every `docker buildx build` sends its trace to Bronto. Use `docker buildx build` rather than `docker build`. On Docker Desktop, `docker build` runs on the built-in `docker` driver regardless of the builder selected with `--use`, so it will not be instrumented. Export `OTEL_SERVICE_NAME` in your shell as well as on the builder. A build emits spans from two processes: BuildKit emits the steps, and the `buildx` CLI emits the root `build` span. Without the shell export the CLI reports `service.name=buildx`, so the root span has a different service identity from its own steps. ## What you will see in Bronto Open [Tracing](https://app.bronto.io/tracing) and filter by your service name — build traces appear under Tracing, not log search. Span names are the Dockerfile steps verbatim, such as `[4/4] RUN npm ci` and `exporting to image`. A step that ran appears under its own name; a step served from cache appears as `load cache: `, emitted for the deepest still-valid step, so it identifies exactly where the cache broke. Grouping spans by name and summing `$span.duration_nano` shows where build time actually goes, and counting `load cache:` spans shows which step invalidates most often. Bronto dashboard showing image export cost by project, total time per build step, where the cache breaks, and average build time by project ## Troubleshooting * **No traces?** Use `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` with the full `/v1/traces` path. The base `OTEL_EXPORTER_OTLP_ENDPOINT` variable appends `/v1/{signal}`, producing `/v1/traces/v1/traces`, and the export then fails silently. Also confirm `OTEL_EXPORTER_OTLP_HEADERS` is set on the builder. * **Trace has no root span?** `OTEL_SERVICE_NAME` is not exported in the shell running the build. * **Slow first build?** A new `docker-container` builder starts with an empty cache. * In CI, [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) sets its own `OTEL_*` variables, which can conflict with these. *** For assistance or questions, contact [support@bronto.io](mailto:support@bronto.io). # Envoy logs, metrics, and traces with OpenTelemetry Source: https://docs.bronto.io/integrations/envoy Collect Envoy access logs, Prometheus metrics, and request traces — downstream connections, response codes, and timing — with the OpenTelemetry Collector. Collect Envoy access logs — downstream/upstream connections, response codes, and timing — with the OpenTelemetry Collector. The same Collector can also receive Envoy's traces and your apps' telemetry — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * Envoy configured with a JSON access log (strongly recommended — see below) * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) installed ## Configure a JSON access log Add a `FileAccessLog` to the HTTP connection manager. Use `typed_json_format` so numeric fields stay numeric: ```yaml envoy.yaml theme={"dark"} access_log: - name: envoy.access_loggers.file typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog path: /var/log/envoy/access.log typed_json_format: method: "%REQ(:METHOD)%" path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%" response_code: "%RESPONSE_CODE%" duration: "%DURATION%" upstream_cluster: "%UPSTREAM_CLUSTER%" bytes_sent: "%BYTES_SENT%" bytes_received: "%BYTES_RECEIVED%" ``` ## Configure the Collector ```yaml /etc/otel/config.yaml theme={"dark"} receivers: filelog/envoy: include: - /var/log/envoy/access.log operators: - type: json_parser resource: service.name: envoy service.namespace: processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/envoy] processors: [batch] exporters: [otlphttp/brontologs] ``` Set `` to `eu` or `us`. Running Envoy as a container or Istio sidecar? It logs to `/dev/stdout` — collect the container logs via the [Docker](/integrations/docker) or [Kubernetes](/integrations/kubernetes) setup instead, and for a mesh see [Istio](/integrations/istio). ## Distributed tracing Envoy can also emit traces natively via the `envoy.tracers.opentelemetry` extension. When Envoy and the Collector share a host, `localhost:4317` is the standard OTLP/gRPC default; otherwise use the Collector address, port, and TLS settings reachable from Envoy. The spans flow to Bronto alongside these logs. See [Send Traces to Bronto](/tracing/send-traces). ## Metrics Envoy exposes Prometheus metrics from its admin interface at `/stats/prometheus`. Scrape that endpoint with the Collector: ```yaml theme={"dark"} receivers: prometheus: config: scrape_configs: - job_name: envoy metrics_path: /stats/prometheus static_configs: - targets: [localhost:9901] ``` Add this receiver to the [Bronto metrics pipeline](/metrics/send-metrics). See the [Collector Contrib Prometheus receiver documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/prometheusreceiver), and keep the admin interface bound to a trusted network. ## What you will see in Bronto Open [Search](https://app.bronto.io/search) and filter by `service.name = envoy`. Each entry carries the downstream remote address, method, path, response code, duration, upstream cluster, and bytes sent/received. JSON format maps directly to searchable attributes; plain-text access logs need Bronto's [Custom Parser](/core-features/custom-parser). ## Troubleshooting * **Unstructured logs?** Use `typed_json_format` (above) rather than the default text format, which requires parsing. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit Envoy's stdout is captured in the container logs, so collect them with Fluent Bit's `tail` input as shown on the [Docker](/integrations/docker) or [Kubernetes](/integrations/kubernetes) pages — set **Format** to `json_lines` (not `json`). See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit). # Fastly Source: https://docs.bronto.io/integrations/fastly Stream Fastly CDN service logs to Bronto in real time using a real-time log streaming endpoint to monitor edge traffic, errors, and cache performance. ## Overview As part of this feature, Fastly provides an option to send data to generic HTTPS endpoints. In this document, we describe how to leverage this feature in order to send Fastly service logs to Bronto. ## Setup ### API Key * First an **API key** is required in order to be able to successfully ingest data into Bronto. To generate an API key in Bronto, please refer to the [API Keys documentation](/Account-Management/API-Keys). ### Fastly Logging Configuration The logging configuration is set per Fastly service (CDN or Compute). * From your CDN Services in Fastly, Select the Service you wish to collect logs from. * Click the Service configuration tab * Click the Logging option on the left sidebar * From here select **Create an Endpoint** option, select **HTTPS** and then **Create endpoint** * Fill in the details required which include: * **Name:** Name of the endpoint to create * **Placement:** Format Version Default * **Log Format:** See example below which can be copied * **URL:** The URL to the Bronto ingestion endpoint. service\_name and service\_namespace query parameters can be passed to the URL in order to define the location of the log data in Bronto for example: ```url URL example theme={"dark"} https://ingestion.eu.bronto.io/?service_name=@field.host&service_namespace=fastly_cdn_service ``` * **Maximum logs:** Max number of log lines sent in a single batch. Bronto does not enforce a limit, so the value can be left 0 * **Maximum bytes:** Max number of bytes sent in a single batch. Bronto accepts payload up to 10MiB, so this should be set to 10485760 * Next Select **Advanced Options** and fill out the required fields: * **Content Type:** The content type used when sending logs. **Required:** application/json. * **Custom header name:** A custom header used when sending logs. **Required:** x-bronto-api-key * **Custom header value:** A custom header value used when sending logs. **Required:** The Bronto API key previously generated * **Method:** **Required:** POST * **JSON log entry format:** **Required:** Newline Delimited * **Select a log line format:** Blank * **Compression:** Zstandard * Finally, select Save or Update See below for an example configuration: For CDN logs, it is possible to specify the format of each log entry, for example: ```json /etc/fastly/fastly.conf theme={"dark"} { "timestamp": "%{strftime({"%Y-%m-%dT%H:%M:%S.%f%z"}, time.start)}V", "client_ip": "%{req.http.Fastly-Client-IP}V", "geo_country": "%{client.geo.country_name}V", "geo_city": "%{client.geo.city}V", "host": "%{if(req.http.Fastly-Orig-Host, req.http.Fastly-Orig-Host, req.http.Host)}V", "url": "%{json.escape(req.url)}V", "request_method": "%{json.escape(req.method)}V", "request_protocol": "%{json.escape(req.proto)}V", "request_referrer": "%{json.escape(req.http.referer)}V", "request_user_agent": "%{json.escape(req.http.User-Agent)}V", "response_state": "%{json.escape(fastly_info.state)}V", "response_status": %{resp.status}V, "response_reason": %{if(resp.response, "%22"+json.escape(resp.response)+"%22", "null")}V, "response_body_size": %{resp.body_bytes_written}V, "fastly_server": "%{json.escape(server.identity)}V", "fastly_is_edge": %{if(fastly.ff.visits_this_service == 0, "true", "false")}V } ``` Congratulations, once the Fastly service logging configuration is activated data will begin to flow to Bronto. Please note it can take some time for the Service and Service Namespace to be created and for logs to flow. ### Using Event Fields for Service Name and Namespace You can configure service name and namespace parameters within the URL to dynamically fetch values from log event content using the format @field.key. ```url Service Name Using geo_countr theme={"dark"} https://ingestion.eu.bronto.io/?service_name=@field.geo_country&service_namespace=fastly ``` In this example, the geo\_country value from the event content will be utilized as the service name. Once setup, logs for each field will go to the relevant Service in Bronto which allows you to send the log events per service using multiple HTTPs logging endpoints with Fastly. # Send Google Cloud Run telemetry to Bronto Source: https://docs.bronto.io/integrations/gcp-cloud-run Send Cloud Run application logs, metrics, and traces through an OpenTelemetry Collector sidecar, and platform request logs through Cloud Logging Pub/Sub. ## Overview For application telemetry, run an OpenTelemetry Collector sidecar in the same Cloud Run service and send logs, metrics, and traces to its configured OTLP receiver. `http://localhost:4318` is the usual OTLP/HTTP default for this sidecar topology, but the address, protocol, and TLS settings must match your Collector configuration. Cloud Run platform request logs remain in Cloud Logging; route those through Pub/Sub when you need them in Bronto too. Do not push Pub/Sub directly to Bronto's HTTP endpoint — Pub/Sub wraps each message in an envelope (base64 `message.data`) that Bronto cannot parse. The OTel Collector unwraps it. ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys)) * A Google Cloud project with Cloud Run services and Cloud Logging enabled (the default) * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) running in your GCP environment (e.g. on Cloud Run or GKE) ## Application telemetry through a sidecar Instrument the application with the [OpenTelemetry SDK](/opentelemetry/overview) and point it at the Collector sidecar. With the receiver configuration below, use the standard local OTLP/HTTP base endpoint `http://localhost:4318`; change it if you customize the receiver. ```yaml /etc/otel/config.yaml theme={"dark"} receivers: otlp: protocols: http: endpoint: 0.0.0.0:4318 processors: batch: exporters: otlphttp/bronto: logs_endpoint: "https://ingestion..bronto.io/v1/logs" metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" traces_endpoint: "https://ingestion..bronto.io/v1/traces" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] metrics: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] traces: receivers: [otlp] processors: [batch] exporters: [otlphttp/bronto] ``` Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). ## Platform request logs through Pub/Sub Cloud Run writes platform request logs to Cloud Logging. To forward them: ```text theme={"dark"} Cloud Run → Cloud Logging → Log sink → Pub/Sub → OTel Collector → Bronto ``` ### Step 1: Route Cloud Run logs to Pub/Sub 1. Create a Pub/Sub topic (e.g. `bronto-cloud-run-logs`) and a pull subscription (e.g. `bronto-cloud-run-logs-sub`). 2. In **Logging → Log Router**, create a sink to that topic with the inclusion filter: ```text theme={"dark"} resource.type="cloud_run_revision" ``` Grant the Collector's service account the `roles/pubsub.subscriber` role. For details, see the [Cloud Logging routing docs](https://cloud.google.com/logging/docs/export/configure_export_v2). ### Step 2: Configure the Collector ```yaml /etc/otel/config.yaml theme={"dark"} receivers: googlecloudpubsub: project: subscription: projects//subscriptions/bronto-cloud-run-logs-sub processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: x-bronto-collection: service: pipelines: logs: receivers: [googlecloudpubsub] processors: [batch] exporters: [otlphttp/brontologs] ``` Set `` to `eu` or `us`. Already have a Pub/Sub sink? Add just the receiver, exporter, and logs pipeline above to your existing Collector. ## What you will see in Bronto Open Search for application and request logs, Metric Explorer for metrics, and Explore Traces for spans. Resource attributes identify the Cloud Run service, revision, project, and region. ## Troubleshooting * **No logs?** Confirm the Log Router sink is active and its filter matches your services; check the Pub/Sub topic's published-message count. * **Collector not receiving?** Verify the subscription exists and the service account has `pubsub.subscriber`, then check the Collector's own logs. * For the receiver reference, see the [`googlecloudpubsub` receiver docs](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/googlecloudpubsubreceiver). # Send Google Kubernetes Engine logs and metrics to Bronto Source: https://docs.bronto.io/integrations/gcp-gke Collect GKE pod logs and kubelet metrics with an OpenTelemetry Collector DaemonSet, or bridge Cloud Logging through Pub/Sub, and forward both to Bronto. ## Overview On **GKE Standard**, the recommended setup is an OpenTelemetry Collector **DaemonSet** that reads pod logs and kubelet metrics from each node. If you already export logs to Cloud Logging — or you run **GKE Autopilot**, which does not permit node-level collection — bridge those logs through Pub/Sub instead. ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys)) * A GKE cluster with `kubectl` and Helm access ## Primary: OTel Collector DaemonSet Deploy the Collector as a DaemonSet with the [OpenTelemetry Helm chart](https://github.com/open-telemetry/opentelemetry-helm-charts/tree/main/charts/opentelemetry-collector). Its presets collect pod logs and add Kubernetes metadata: ```yaml values.yaml theme={"dark"} mode: daemonset presets: logsCollection: enabled: true kubernetesAttributes: enabled: true kubeletMetrics: enabled: true config: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: x-bronto-collection: otlphttp/brontometrics: metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: exporters: [otlphttp/brontologs] metrics: exporters: [otlphttp/brontometrics] ``` ```bash theme={"dark"} helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts helm install otel-collector open-telemetry/opentelemetry-collector -f values.yaml ``` Set `` to `eu` or `us`. This reads pod logs from the node and bypasses Cloud Logging. For more Collector detail, see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). For volume or request/limit utilization metrics, grant the Collector service account `get` access to `nodes/proxy`. **GKE Autopilot:** this DaemonSet path does not work. Autopilot does not support node-level log collection, and it blocks the `nodes/proxy` access the `kubeletMetrics` preset needs — enabling it leaves the DaemonSet crash-looping on privilege errors. On Autopilot, collect logs through the Pub/Sub bridge below, and get metrics and traces by exporting OTLP from each application (see [Ingest OpenTelemetry data](/opentelemetry/overview)). For receiver settings, authentication, and available measurements, see the [Collector Contrib Kubelet Stats receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/kubeletstatsreceiver). ## Alternative: Cloud Logging via Pub/Sub If you already route logs through Cloud Logging — or you are on Autopilot — create a Log Router sink to a Pub/Sub topic and read it with the `googlecloudpubsub` receiver. Use the inclusion filter `resource.type="k8s_container"`, create a pull subscription on the topic, and grant the Collector's service account `roles/pubsub.subscriber` (via Workload Identity). See the [Cloud Logging routing docs](https://cloud.google.com/logging/docs/export/configure_export_v2). ```yaml /etc/otel/config.yaml theme={"dark"} receivers: googlecloudpubsub: project: subscription: projects//subscriptions/bronto-gke-logs-sub processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: x-bronto-collection: service: pipelines: logs: receivers: [googlecloudpubsub] processors: [batch] exporters: [otlphttp/brontologs] ``` Don't push Pub/Sub directly to Bronto — its message envelope isn't parseable. The Collector unwraps it. ## What you will see in Bronto Open Search for pod logs and the Metric Explorer for kubelet metrics. Kubernetes resource attributes identify the pod, namespace, node, and container. ## Troubleshooting * **No logs (DaemonSet)?** Confirm the DaemonSet runs on every node and the `kubernetesAttributes` preset's RBAC is in place. * **No metrics?** Confirm the `kubeletMetrics` preset is enabled and the Collector can reach each node's kubelet. * **DaemonSet crash-looping on GKE Autopilot?** Autopilot blocks `nodes/proxy` and node-level log collection — use the Pub/Sub bridge for logs and per-application OTLP for metrics instead. * **No logs (Pub/Sub)?** Verify the sink is active and the Collector's service account has `roles/pubsub.subscriber`. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). # Grafana Plugin Source: https://docs.bronto.io/integrations/grafana-plugin Install the Bronto data source plugin for Grafana to query log data in Explore, build dashboards, and view Bronto logs beside other Grafana sources. ## Overview The Bronto data source plugin lets you search Bronto log data from inside Grafana, without leaving the dashboards your team already uses. Once connected you can: * Search log events with Bronto's SQL-style filter syntax, rendered in Grafana's Logs panel and Explore, with a log volume histogram. * Aggregate with functions such as `count(*)` and `avg(response_time_ms)` and plot the result as a time series. * Group by one or more fields to break an aggregation into a multi-series graph. * Query multiple datasets at once from a searchable picker grouped by collection. The plugin covers log data only. Traces and metrics are not queryable through it today. This guide is for self-managed Grafana. The plugin is distributed as a zip file rather than through the Grafana plugin catalog, so Grafana treats it as an unsigned plugin and you have to allow it explicitly. Grafana Cloud does not load unsigned plugins. If you run Grafana Cloud, contact Bronto support. ## Prerequisites * Grafana 12.3.0 or later, self-managed. Check your version from the help menu in Grafana, or run `grafana server -v` on the server. * Administrator access to the Grafana host, so you can write to the plugin directory and edit `grafana.ini`. For containerized deployments, access to the compose file or Helm values is enough. * Network egress from the Grafana server to Bronto. The plugin's backend, not your browser, calls the Bronto API, so the Grafana host must reach `api..bronto.io` on port 443. * A Bronto API key with the Search role. Creating one requires the Admin role in Bronto. See [API Keys](/Account-Management/API-Keys). Your Bronto API base URL depends on your account's region: | Region | API base URL | | - | - | | EU | `https://api.eu.bronto.io` | | US | `https://api.us.bronto.io` | ## Step 1: Download and verify the plugin 1. Open the [releases page](https://github.com/bronto-community/bronto-grafana-datasource/releases) and find the latest release. 2. Download the plugin archive and its checksum. Take the `brontoio-bronto-datasource-.zip` asset, not the "Source code" archives. ```bash theme={"dark"} curl -LO https://github.com/bronto-community/bronto-grafana-datasource/releases/download/v1.0.0/brontoio-bronto-datasource-1.0.0.zip curl -LO https://github.com/bronto-community/bronto-grafana-datasource/releases/download/v1.0.0/brontoio-bronto-datasource-1.0.0.zip.sha1 ``` Confirm the archive matches its published checksum: ```bash theme={"dark"} sha1sum brontoio-bronto-datasource-1.0.0.zip # on macOS: shasum cat brontoio-bronto-datasource-1.0.0.zip.sha1 ``` The two values should be identical. ## Step 2: Install the plugin Pick the path that matches how you run Grafana. Grafana loads plugins from the directory set by `plugins` under `[paths]` in `grafana.ini`, or by the `GF_PATHS_PLUGINS` environment variable. The defaults are `/var/lib/grafana/plugins` on Linux and `/usr/local/var/lib/grafana/plugins` on macOS. The archive already contains a top-level `brontoio-bronto-datasource/` folder, so extract it into the plugin directory itself: ```bash theme={"dark"} sudo unzip brontoio-bronto-datasource-1.0.0.zip -d /var/lib/grafana/plugins/ sudo chown -R grafana:grafana /var/lib/grafana/plugins/brontoio-bronto-datasource ``` The second command matters: files extracted as `root` are often unreadable by the account Grafana runs under. ### Alternative: install with the Grafana CLI The Grafana CLI can fetch and unpack the archive for you: ```bash theme={"dark"} sudo grafana cli --pluginUrl https://github.com/bronto-community/bronto-grafana-datasource/releases/download/v1.0.0/brontoio-bronto-datasource-1.0.0.zip plugins install brontoio-bronto-datasource ``` If `grafana` is not on your `PATH`, call it by full path: `/usr/share/grafana/bin/grafana` on Linux. Have Grafana install the plugin from the release URL on startup, and allow it in the same place. In `docker-compose.yaml`: ```yaml theme={"dark"} services: grafana: image: grafana/grafana:latest environment: GF_PLUGINS_PREINSTALL_SYNC: brontoio-bronto-datasource@1.0.0@https://github.com/bronto-community/bronto-grafana-datasource/releases/download/v1.0.0/brontoio-bronto-datasource-1.0.0.zip GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: brontoio-bronto-datasource ``` `GF_PLUGINS_PREINSTALL_SYNC` takes the format `@@`. If you would rather not download at startup, extract the archive on the host and mount it at `/var/lib/grafana/plugins/brontoio-bronto-datasource` instead, keeping the `GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS` variable. With the Grafana Helm chart, add the release URL to `plugins` and allow the plugin in `grafana.ini`: ```yaml theme={"dark"} plugins: - https://github.com/bronto-community/bronto-grafana-datasource/releases/download/v1.0.0/brontoio-bronto-datasource-1.0.0.zip;brontoio-bronto-datasource grafana.ini: plugins: allow_loading_unsigned_plugins: brontoio-bronto-datasource ``` The `;brontoio-bronto-datasource` suffix tells the chart which plugin ID the archive contains. Once both values are set, skip to Step 4. ## Step 3: Allow the unsigned plugin Grafana refuses to load unsigned plugins unless you name them explicitly. Add the plugin ID to `grafana.ini`: ```ini theme={"dark"} [plugins] allow_loading_unsigned_plugins = brontoio-bronto-datasource ``` If you already allow other unsigned plugins, add this one to the existing comma-separated list. The environment variable equivalent is: ```bash theme={"dark"} GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=brontoio-bronto-datasource ``` ## Step 4: Restart Grafana ```bash theme={"dark"} sudo systemctl restart grafana-server ``` For containers, restart the container or roll the pod. A configuration reload is not enough: Grafana scans for plugins at startup. ## Step 5: Confirm the plugin loaded 1. Sign in to Grafana as an administrator. 2. Go to **Administration > Plugins and data > Plugins** and search for Bronto. 3. Grafana shows the plugin with an unsigned signature status. That is expected, and the server log records it: ```text theme={"dark"} level=warn msg="Plugin is unsigned" id=brontoio-bronto-datasource level=warn msg="Permitting unsigned plugin. This is not recommended" pluginId=brontoio-bronto-datasource ``` If the plugin is missing entirely, see [Troubleshooting](#troubleshooting). ## Step 6: Create a Bronto API key The plugin only reads: it calls Bronto's search, dataset and field-name endpoints. The Search role covers all three and grants no write access. The Admin role also works but is broader than the plugin needs, and the Ingestion role does not work at all. Bronto displays the key once. If you lose it, create a new one. ## Step 7: Add the Bronto data source 1. In Grafana, go to **Connections > Data sources > Add new data source**. 2. Search for and select **Bronto**. 3. Fill in the connection settings: * **Base URL** - the API base URL for your region, with no trailing slash, for example `https://api..bronto.io`. * **API Key** - the key from Step 6. Grafana stores it encrypted on the server and never returns it to the browser. 4. Select **Save & test**. On success Grafana reports `Successfully connected to Bronto`. ### Provisioning the data source as code To create the data source from a provisioning file instead of the UI, add it under `provisioning/datasources/`: ```yaml theme={"dark"} apiVersion: 1 datasources: - name: Bronto type: brontoio-bronto-datasource access: proxy isDefault: false orgId: 1 version: 1 editable: true jsonData: baseUrl: "https://api..bronto.io" secureJsonData: apiKey: "" ``` ## Run your first query Open Explore, select the Bronto data source, and use the query editor: | Field | What it does | | - | - | | Dataset | One or more datasets to search, grouped by collection. At least one is required. | | Query | A where-style filter, for example `@status = 'error' AND service = 'checkout'`. Leave it empty to return every event in the time range. | | Aggregation | An optional select expression such as `count(*)` or `avg(response_time_ms)`. | | Group By | Optional fields to split an aggregation by, producing one series per group. | The Aggregation field decides what comes back. Leave it empty and the query returns log events, best viewed as Logs or in Explore. Set it and the query returns a time series you can plot on a graph panel. Filters support `=`, `!=`, `>`, `<`, `>=`, `<=`, `AND`, `OR`, `NOT`, `LIKE` and `IN`. Press **Ctrl+Space** in the Query field for field, operator and keyword suggestions drawn from the datasets you selected. For the full syntax, see [Search Syntax](/query-syntax/search-syntax). A first query worth running: select one dataset, leave Query and Aggregation empty, and set the time range to the last 15 minutes. You should see recent events and a volume histogram. Then set Aggregation to `count(*)` to turn the same query into a time series, and add a Group By field such as `service` to split it. ## Upgrading and removing Because the plugin is installed by hand rather than from the Grafana catalog, it does not update itself. To upgrade, delete the existing plugin folder, extract the new release in its place, and restart Grafana. Your data sources and dashboards are unaffected, since they reference the plugin by ID. ```bash theme={"dark"} sudo rm -rf /var/lib/grafana/plugins/brontoio-bronto-datasource sudo unzip brontoio-bronto-datasource-.zip -d /var/lib/grafana/plugins/ sudo chown -R grafana:grafana /var/lib/grafana/plugins/brontoio-bronto-datasource sudo systemctl restart grafana-server ``` To remove the plugin, delete any Bronto data sources in **Connections > Data sources**, delete the plugin folder, remove the plugin ID from `allow_loading_unsigned_plugins`, and restart. Panels that queried a deleted data source keep their configuration but return an error until they are pointed elsewhere. ## Current limitations * Log data only. Bronto traces and metrics cannot be queried through the plugin. * Not in the Grafana plugin catalog, so it cannot be installed from the Grafana UI, does not auto-update, and is not available on Grafana Cloud. * Supported platforms: Linux (x86-64, arm64, arm), macOS (x86-64, Apple silicon) and Windows (x86-64). There is no 32-bit x86 or Windows arm64 build. ## Troubleshooting ### Bronto does not appear when you add a data source The plugin did not load. Confirm the plugin ID in `allow_loading_unsigned_plugins` reads exactly `brontoio-bronto-datasource`, that the folder sits directly inside the plugin directory (`/var/lib/grafana/plugins/brontoio-bronto-datasource/plugin.json` should exist), and that Grafana was fully restarted rather than reloaded. ### Save & test returns "Failed to connect to Bronto" The Grafana server could not reach the Bronto API. Check that the Base URL starts with `https://`, names the right region, and has no trailing slash, then confirm the Grafana host itself can reach it: ```bash theme={"dark"} curl -I https://api..bronto.io ``` If your network requires an outbound proxy, Grafana's backend must be configured to use it. ### Save & test returns "Bronto returned HTTP 401" or "403" The key is wrong, was revoked, or lacks read access. Create a fresh key with the Search role and paste it again, checking for leading or trailing whitespace. ### Queries return "at least one dataset is required" Select at least one dataset in the query editor's Dataset field. ### The plugin appears but queries fail, and the log mentions gpx\_bronto The backend process could not start. Check the Grafana log (`/var/log/grafana/grafana.log` by default) and confirm the plugin files are owned by the account Grafana runs as, that the backend binary is executable, and that your platform is on the supported list above. Archives expanded by tools that discard file permissions, such as PowerShell's `Expand-Archive`, produce a non-executable binary. Re-extract with a tool that preserves them, or restore the permission with `chmod +x`. ### A query returns no data even though the dataset has events Widen the Grafana time range, and confirm in Bronto's own search that the dataset has events in that window. # HAProxy logs and metrics with OpenTelemetry Source: https://docs.bronto.io/integrations/haproxy Collect HAProxy access logs and proxy metrics — request latency, status codes, and backend health — with the OpenTelemetry Collector and Prometheus. Collect HAProxy access logs — frontend/backend connections, timing, and status codes — with the OpenTelemetry Collector. HAProxy emits logs over syslog, so the usual setup is HAProxy → rsyslog → a file the Collector tails. The same Collector can also forward traces and metrics from your apps — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * HAProxy logging to local syslog (`log 127.0.0.1 local0` in `haproxy.cfg`), with rsyslog writing `local0` to `/var/log/haproxy.log` * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) installed on the same host ## Configure the Collector ```yaml /etc/otel/config.yaml theme={"dark"} receivers: filelog/haproxy: include: - /var/log/haproxy.log resource: service.name: haproxy service.namespace: processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/haproxy] processors: [batch] exporters: [otlphttp/brontologs] ``` Set `` to `eu` or `us`. No rsyslog on the host? Receive HAProxy's syslog stream directly with the OTel Collector's `syslog` receiver instead of `filelog`. ## Metrics HAProxy 2.0 and later can expose Prometheus metrics through its built-in `prometheus-exporter` service. Enable a stats listener, then scrape it with the Collector's `prometheus` receiver: ```text haproxy.cfg theme={"dark"} frontend prometheus bind 127.0.0.1:8404 mode http http-request use-service prometheus-exporter if { path /metrics } no log ``` ```yaml theme={"dark"} receivers: prometheus: config: scrape_configs: - job_name: haproxy metrics_path: /metrics static_configs: - targets: [localhost:8404] ``` Add this receiver to the [Bronto metrics pipeline](/metrics/send-metrics). See the [Collector Contrib Prometheus receiver documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/prometheusreceiver) for scrape configuration. Older HAProxy releases require a separate exporter or the [Collector Contrib HAProxy receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/haproxyreceiver) against a compatible stats endpoint. ## What you will see in Bronto Open [Search](https://app.bronto.io/search) and filter by `service.name = haproxy`. The HTTP log format includes the client IP, the frontend and backend names, the chosen server, connection and response timers (queue, connect, response, total), the status code, bytes, and the session termination state. Bronto's [Custom Parser](/core-features/custom-parser) has built-in HAProxy support, so these fields are extracted automatically. ## Troubleshooting * **No logs?** Confirm `log 127.0.0.1 local0` is set in `haproxy.cfg` and that rsyslog routes `local0.*` to `/var/log/haproxy.log`, then restart both services. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit If you already run Fluent Bit, tail the HAProxy log file and forward it over HTTP: ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/haproxy.log tag haproxy [OUTPUT] name http match haproxy host ingestion..bronto.io port 443 tls on format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset haproxy header x-bronto-collection ``` Set **Format** to `json_lines`, not `json`. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit) for installation. # Send Heroku Fir telemetry to Bronto Source: https://docs.bronto.io/integrations/heroku-fir Forward logs, metrics, and traces from Heroku Fir apps to Bronto with a native OpenTelemetry telemetry drain — no Logplex, proxy, or Collector needed. ## Overview Heroku's Fir generation exports logs, metrics, and traces as OpenTelemetry signals. A **telemetry drain** forwards all three straight to Bronto — no Logplex, proxy, or intermediate Collector. ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys)) * A Heroku **Fir**-generation app * The [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) installed and authenticated ## Add the telemetry drain Add a drain on your app pointing at Bronto's ingestion endpoint: ```bash theme={"dark"} heroku telemetry:add https://ingestion..bronto.io \ --app \ --signals logs,metrics,traces \ --transport http \ --headers '{"x-bronto-api-key":"","x-bronto-dataset":"","x-bronto-collection":""}' ``` Set `` to `eu` or `us`. Heroku appends the signal-specific OTLP paths. Telemetry drains are additive, so this adds Bronto alongside existing drains. You can select a subset of signals if needed. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). ## Verify in Bronto Open Search for logs, Metric Explorer for metrics, and Explore Traces for spans. Generate activity in your app and confirm all configured signals arrive. List drains with `heroku telemetry --app `. ## What you will see in Bronto Logs arrive as OTLP records carrying the app's stdout/stderr output plus Heroku resource attributes — `service.name`, severity, and timestamp. Platform logs (router, build, and dyno lifecycle events) are included alongside your application output. ## Troubleshooting * **Missing signals?** Run `heroku telemetry --app ` and confirm the drain lists `logs`, `metrics`, and `traces`. * **Getting 401 errors?** Verify the `x-bronto-api-key` value is a valid Bronto key with the Ingestion role. * **Wrong dataset or collection?** Check the `x-bronto-dataset` and `x-bronto-collection` headers in the drain's `--headers` JSON. # Host metrics with OpenTelemetry Source: https://docs.bronto.io/integrations/host-metrics Collect CPU, memory, disk, filesystem, network, paging, process, and system-load metrics with the OpenTelemetry Collector and send them to Bronto. Use the OpenTelemetry Collector's `hostmetrics` receiver to collect operating-system metrics from Linux, Windows, and macOS hosts. Run one Collector on each host so the measurements describe the machine where the Collector is running. Bronto supports sums, gauges, summaries, and explicit histograms. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). ## Prerequisites * A Bronto API key with ingestion permissions * The OpenTelemetry Collector Contrib distribution installed on the host * Network access to `https://ingestion..bronto.io:443` ## Configure the Collector ```yaml /etc/otel/config.yaml theme={"dark"} receivers: hostmetrics: collection_interval: 30s scrapers: cpu: disk: filesystem: load: memory: network: paging: process: processes: system: processors: resourcedetection: detectors: [env, system] system: hostname_sources: [os] batch: exporters: otlphttp/brontometrics: metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" compression: gzip headers: x-bronto-api-key: service: pipelines: metrics: receivers: [hostmetrics] processors: [resourcedetection, batch] exporters: [otlphttp/brontometrics] ``` Replace `` with `eu` or `us`. Remove any scraper you do not need. Some scrapers or individual measurements are operating-system specific. If the Collector runs in a container, it sees the container's filesystem and process namespace by default. Mount the host filesystem and set the receiver's root path according to the Collector distribution documentation, or install the Collector directly on the host. ## Add application telemetry The configuration above collects host metrics. The same Collector can also receive application logs, metrics, and traces over OTLP. Add the `otlp` receiver and the corresponding pipelines from [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). ## Verify delivery Open the Metric Explorer and select a `system.*`, `process.*`, or `system.network.*` metric. Confirm that the resource attributes identify the expected host. ## Troubleshooting * **No metrics:** confirm the Collector build includes the `hostmetrics` receiver. * **Missing process metrics:** check that the Collector user can inspect other processes on the host. * **Missing filesystem metrics:** check filesystem include/exclude filters and container mounts. * **Unexpected hostname:** configure `hostname_sources` explicitly in the `resourcedetection` processor. For receiver-specific options, see the [OpenTelemetry host metrics receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/hostmetricsreceiver). # Ingesting Infrastructure Telemetry into Bronto Source: https://docs.bronto.io/integrations/infrastructure-overview An overview of self-hosted infrastructure and database integrations that send logs, metrics, and traces to Bronto. ## Overview These integrations collect logs, metrics, and, for some sources, request traces from self-hosted infrastructure and databases. Each page documents the signals the source actually exposes and the configuration used to send them to Bronto — an OpenTelemetry Collector pipeline for most sources, and the source's own exporter settings where it speaks OTLP itself. These pages cover infrastructure and middleware you run yourself. To collect logs, metrics, and traces from your own **application code**, instrument it with the [OpenTelemetry SDK](/opentelemetry/overview). *** ## Supported sources Each source below links to a per-integration page with the exact receiver configuration and where that technology writes its logs. All of them are collected with the OpenTelemetry Collector. | Source | Type | Collected | | - | - | - | | [Kubernetes](./kubernetes) | Container platform | Pod logs, kubelet metrics, and application telemetry | | [Docker](./docker) | Container platform | Container logs and runtime metrics | | [Docker Build](./docker-build) | Build system | BuildKit build traces (per-step durations and cache hits) | | [Host metrics](./host-metrics) | Operating system | CPU, memory, disk, filesystem, network, paging, and process metrics | | [NGINX](./nginx) | Web server / proxy | Access and error logs, server metrics, and request traces | | [HAProxy](./haproxy) | Load balancer / proxy | Access logs and Prometheus metrics | | [Traefik](./traefik) | Reverse proxy | Access logs and Prometheus metrics | | [Envoy](./envoy) | Proxy | Access logs, Prometheus metrics, and request traces | | [Istio](./istio) | Service mesh | Mesh access logs, Envoy metrics, and traces | | [Keycloak](./keycloak) | Identity provider | Login, token, and JDBC traces, trace-correlated server logs, and Prometheus metrics | | [Kafka](./kafka) | Message broker | Broker logs and cluster/consumer metrics | | [RabbitMQ](./rabbitmq) | Message broker | Broker logs and queue metrics | | [PostgreSQL](./postgresql) | Database | Server logs and database metrics | | [MySQL](./mysql) | Database | Error/slow-query logs and database metrics | | [MongoDB](./mongodb) | Database | Server logs and database metrics | | [Redis](./redis) | Database / cache | Server logs and cache metrics | *** ## Ingestion method Most sources in this section are collected with the [OpenTelemetry Collector](/agent-setup/open-telemetry). [Docker Build](./docker-build) and [Keycloak](./keycloak) are the exceptions — both are already instrumented with OpenTelemetry and export their traces to Bronto directly, with no Collector in between. Keycloak's metrics are the usual Prometheus scrape. Log receivers tail files or container output, while metric receivers scrape the source's monitoring endpoint or operating-system APIs. The Collector forwards only what it receives, so each integration page identifies the source-side feature that must be enabled. For Windows hosts, see [Collecting Windows OS Logs and Metrics](./azure-windows-logs) for Windows Event Log and IIS collection, plus Windows performance-counter, IIS, and SQL Server metrics. *** For assistance or questions, contact [support@bronto.io](mailto:support@bronto.io). # Istio logs, metrics, and traces with OpenTelemetry Source: https://docs.bronto.io/integrations/istio Collect Istio access logs, Envoy sidecar metrics, and mesh traces with the OpenTelemetry Collector, enabling access logging through the Telemetry API. Istio's access logs come from the Envoy sidecar in each pod. Enable them with the `Telemetry` API, then collect the sidecar stdout with the same pod-log collector you use for the rest of the cluster. ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * Istio installed with sidecar injection enabled (Istio 1.12+ for the `Telemetry` API) * A pod-log collector already running — see [Kubernetes](/integrations/kubernetes) ## Enable Istio access logging Apply a mesh-wide `Telemetry` resource in the `istio-system` namespace using the built-in `envoy` provider, which logs to each sidecar's stdout: ```yaml telemetry.yaml theme={"dark"} apiVersion: telemetry.istio.io/v1 kind: Telemetry metadata: name: mesh-default namespace: istio-system spec: accessLogging: - providers: - name: envoy ``` ```bash theme={"dark"} kubectl apply -f telemetry.yaml ``` To scope logging to a single namespace, apply the resource there instead of `istio-system`. ## Collect with your existing setup Once access logging is on, sidecars write to stdout — your [Kubernetes DaemonSet](/integrations/kubernetes) already forwards pod logs to Bronto, so no extra collector config is needed. Use the `x-bronto-collection` header to tag the cluster. ## Distributed tracing The same `Telemetry` API can enable mesh tracing: add a `tracing` provider that points at an OpenTelemetry Collector, which exports spans to Bronto. See [Send Traces to Bronto](/tracing/send-traces). ## Metrics Istio sidecars expose Envoy metrics on port `15090` at `/stats/prometheus`. Add a Prometheus receiver with Kubernetes service discovery, or extend your existing Prometheus/OpenTelemetry pipeline, and export those metrics to Bronto: ```yaml theme={"dark"} receivers: prometheus: config: scrape_configs: - job_name: istio-proxies metrics_path: /stats/prometheus kubernetes_sd_configs: - role: pod ``` Filter the scrape targets to injected pods and port `15090` in production. See the [Collector Contrib Prometheus receiver documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/prometheusreceiver) for discovery and relabeling options, and [Send Metrics to Bronto](/metrics/send-metrics) for the exporter configuration and supported metric types. ## What you will see in Bronto Filter by your collection. Each request log includes the source and destination workload and namespace, method, path, response code, duration, bytes, and Envoy response flags. Bronto's [Custom Parser](/core-features/custom-parser) extracts these fields. ## Troubleshooting * **No access logs?** Confirm the sidecar is injected (`kubectl get pod -o jsonpath='{.spec.containers[*].name}'` should list `istio-proxy`) and that the `Telemetry` resource is in `istio-system`. * **Older Istio (pre-1.12):** the `Telemetry` API isn't available — enable access logs through the mesh config (`accessLogFile: /dev/stdout`) instead. * For collection issues, see the [Kubernetes](/integrations/kubernetes) page. ## Alternative: Fluent Bit Collection is handled by your pod-log agent, so if you run the Fluent Bit DaemonSet from the [Kubernetes](/integrations/kubernetes) page, Istio access logs are already included — no Istio-specific Fluent Bit config is required. # Apache Kafka logs and metrics with OpenTelemetry Source: https://docs.bronto.io/integrations/kafka Collect Apache Kafka broker logs and cluster metrics — controller and request logs, partitions, and consumer lag — with the OpenTelemetry Collector. Collect Apache Kafka broker logs — the Log4j application logs such as `server.log` — with the OpenTelemetry Collector. The same Collector can also forward traces and metrics from your apps — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). This covers the broker's operational logs, not the commit-log data Kafka stores for topics. ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * Kafka brokers writing Log4j logs to disk. The default location is `$KAFKA_HOME/logs/` (often `/var/log/kafka/`), with `server.log` as the main broker log * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) installed on the same host ## Configure the Collector Kafka stack traces span multiple lines. Use `multiline` keyed on the Log4j `[timestamp]` prefix: ```yaml /etc/otel/config.yaml theme={"dark"} receivers: filelog/kafka: include: - /var/log/kafka/server.log - /var/log/kafka/controller.log multiline: line_start_pattern: '^\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}\]' resource: service.name: kafka service.namespace: processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/kafka] processors: [batch] exporters: [otlphttp/brontologs] ``` Set `` to `eu` or `us`. ## Metrics The Collector Contrib `kafkametrics` receiver reads broker, topic, partition, and consumer-group state from the Kafka protocol: ```yaml theme={"dark"} receivers: kafkametrics: brokers: [localhost:9092] protocol_version: scrapers: [brokers, topics, consumers] collection_interval: 30s ``` Set `protocol_version` to a value supported by your cluster and Collector version, then add the receiver to the [Bronto metrics pipeline](/metrics/send-metrics). See the [Collector Contrib Kafka Metrics receiver documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/kafkametricsreceiver) for authentication and scraper options. Use a JMX-based receiver when you also need JVM and broker-process measurements. ## What you will see in Bronto Open [Search](https://app.bronto.io/search) and filter by `service.name = kafka`. Entries follow the Log4j pattern — timestamp, level (`INFO`, `WARN`, `ERROR`), logger, and message — covering broker lifecycle, controller and partition events, ISR changes, and exceptions with stack traces (kept intact by the multiline setting). Bronto's [Custom Parser](/core-features/custom-parser) extracts these fields server-side. ## Distributed tracing The Kafka broker does not emit traces — Apache Kafka has no native tracing, so the entries above are the broker's operational logs only. To trace messages end to end, instrument your **producer and consumer applications** with the OpenTelemetry SDK: it creates send/receive spans and propagates trace context through Kafka message headers. Point those apps at the same Collector and traces flow to Bronto alongside these logs — see [Send Traces to Bronto](/tracing/send-traces) and the [OpenTelemetry SDK guides](/opentelemetry/overview). On Kubernetes, [Strimzi](https://strimzi.io/) can additionally enable OpenTelemetry tracing for Kafka Connect, MirrorMaker, and the Kafka Bridge. ## Troubleshooting * **Where are the logs?** Check the `kafka.logs.dir` / `LOG_DIR` setting or the appender file path in your `log4j.properties`, and adjust `include`. * **Want structured fields at the source?** Configure a Log4j JSON layout for direct field extraction. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit If you already run Fluent Bit, tail the broker log files and forward them over HTTP. The built-in `java` multiline parser keeps stack traces intact: ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/kafka/server.log,/var/log/kafka/controller.log multiline.parser java tag kafka [OUTPUT] name http match kafka host ingestion..bronto.io port 443 tls on format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset kafka header x-bronto-collection ``` Set **Format** to `json_lines`, not `json`. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit) for installation. # Keycloak traces and logs with OpenTelemetry Source: https://docs.bronto.io/integrations/keycloak Turn on Keycloak's built-in OpenTelemetry exporter to send login, token and JDBC traces — plus trace-correlated server logs — to Bronto over OTLP. Keycloak has shipped an OpenTelemetry exporter since 26.0. Seven lines in `conf/keycloak.conf` turn it on and point it at Bronto over OTLP/HTTP — no Collector, no Java agent, nothing installed. Every login, token grant and JDBC statement becomes a span, and the server's own log stream can travel over the same connection, already correlated by trace ID. ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * Keycloak 26.0 or later (verified with 26.7.1, embedded Quarkus 3.33.2.1 and OpenTelemetry Java SDK 1.57.0) * Tracing is gated behind the `opentelemetry` preview feature, which the configuration below enables ## Configure Keycloak Add to `conf/keycloak.conf`: ```ini conf/keycloak.conf theme={"dark"} features=opentelemetry,opentelemetry-logs tracing-enabled=true telemetry-logs-enabled=true telemetry-protocol=http/protobuf telemetry-endpoint=https://ingestion..bronto.io telemetry-header-x-bronto-api-key=${BRONTO_API_KEY} telemetry-service-name= ``` Set `` to `eu` or `us`, export `BRONTO_API_KEY` in the server's environment, and restart Keycloak. `features` is a build-time option, so `start` re-augments the server on the next boot. `telemetry-endpoint` takes the **host only**. Keycloak appends `/v1/traces` and `/v1/logs` itself — pass a full signal URL and it will POST to `/v1/traces/v1/traces`. `telemetry-protocol=http/protobuf` is not optional. The exporter defaults to gRPC, which Bronto's ingestion endpoint does not accept. `${BRONTO_API_KEY}` is resolved by Keycloak at boot, so the key stays out of the config file and out of your image. The single `telemetry-header-*` line is inherited by the logs exporter as well as the tracer. `telemetry-service-name` sets `service.name` across Keycloak's telemetry. For logs, the value also selects the dataset. For traces, it identifies the service in Explore Traces; traces do not belong to a dataset or collection. The two signals appear in different product areas: logs in the selected log dataset, and traces in Explore Traces. Drop `opentelemetry-logs` from `features` and `telemetry-logs-enabled` if you only want traces. ### Option naming On 26.7 the endpoint, protocol, service-name and resource-attribute options were generalised from the `tracing-*` family to `telemetry-*`, which is shared with logs. `tracing-service-name` and `tracing-resource-attributes` are marked deprecated in `--help-all`. The older `tracing-*` spellings still work, but `tracing-enabled` was **not** renamed — there is no `telemetry-enabled`, which is why the block above mixes the two families. ### Environment variables instead Every option has a `KC_*` twin, which suits a Kubernetes Deployment or a Compose file: ```bash theme={"dark"} KC_FEATURES=opentelemetry,opentelemetry-logs KC_TRACING_ENABLED=true KC_TELEMETRY_LOGS_ENABLED=true KC_TELEMETRY_PROTOCOL=http/protobuf KC_TELEMETRY_ENDPOINT=https://ingestion..bronto.io KC_TELEMETRY_HEADER_X_BRONTO_API_KEY= KC_TELEMETRY_SERVICE_NAME= ``` ## Metrics Keycloak also exposes Prometheus metrics, on its management port and separately from the OTLP exporter above. Add to `conf/keycloak.conf`: ```ini conf/keycloak.conf theme={"dark"} metrics-enabled=true event-metrics-user-enabled=true ``` and add `user-event-metrics` to the `features` line: ```ini conf/keycloak.conf theme={"dark"} features=opentelemetry,opentelemetry-logs,user-event-metrics ``` `metrics-enabled=true` on its own gives JVM, HTTP, Infinispan cache and JDBC pool metrics — 260 families. The `user-event-metrics` feature adds the counters specific to an identity provider: | Metric | Labels | What it answers | | - | - | - | | `keycloak_user_events_total` | `realm`, `event`, `error` | Logins, client logins and token refreshes per realm, and the reason when one fails | | `keycloak_credentials_password_hashing_validations_total` | `realm`, `algorithm`, `hashing_strength`, `outcome` | Which hash algorithm and cost factor each realm is really running | | `agroal_active_count`, `agroal_available_count`, `agroal_awaiting_count`, `agroal_blocking_time_total_milliseconds` | `datasource` | JDBC pool depth, and time spent waiting for a connection | | `http_server_requests_seconds` | `method`, `uri`, `status`, `outcome` | Request latency histogram, with `uri` templated the same way span names are | Scrape the endpoint with the OpenTelemetry Collector: ```yaml theme={"dark"} receivers: prometheus: config: scrape_configs: - job_name: keycloak scrape_interval: 15s scheme: https static_configs: - targets: [:9000] ``` Add this receiver to the [Bronto metrics pipeline](/metrics/send-metrics). Prometheus counters are cumulative, so include the `cumulativetodelta` processor — Bronto accepts both, and recommends delta. The management interface inherits the server's TLS configuration: once `https-certificate-file` is set, port `9000` serves HTTPS, and the scrape config needs `scheme: https` as above. ### Exporting metrics over OTLP instead Keycloak can also export metrics over OTLP directly, reusing the endpoint and header already configured for traces — add `opentelemetry-metrics` to `features`, and set `telemetry-metrics-enabled=true` alongside `metrics-enabled=true`. No Collector is involved. Two things to weigh against the scrape above. The feature is Experimental rather than Preview, and Keycloak escalates its startup banner accordingly. And the series arrive cumulative, under OpenTelemetry's dotted names (`keycloak.credentials.password.hashing`) rather than the Prometheus spellings in the table above, so the two routes do not produce interchangeable metric names. ## What you will see in Bronto Open [Tracing](https://app.bronto.io/tracing) and filter by your service name. A browser login is one trace of about 28 spans, rooted at `POST /realms/{realm}/login-actions/authenticate`. Token requests root at `TokenEndpoint.processGrantRequest`. JDBC is instrumented by default, so every statement appears with `$db.statement`, `$db.sql.table` and `$db.operation` attached. Span names are templated, so the realm is not in the name — `$url.path` carries it. Grouping login spans by `$url.path` shows latency per realm, and grouping token spans by grant type shows what each kind of token costs. Grant type, realm, client and outcome arrive as a **span event** rather than span attributes: `$span.events.0.name` is `LOGIN`, `REFRESH_TOKEN`, `CODE_TO_TOKEN` or `LOGIN_ERROR`, with `$span.events.0.kc.details.grant_type`, `.kc.realmName` and `.kc.clientId` alongside it. Grouping by an event key needs it quoted inside the query string — `"groups": ["\"$span.events.0.kc.details.grant_type\""]` — though the same key needs no quoting in a filter. A failed login is not a span error. It is an HTTP 200 re-render or a 400, and its status is `STATUS_CODE_UNSET` just like a success, so filter on `$http.response.status_code` or on the `LOGIN_ERROR` span event rather than on span status. ## Troubleshooting * **No traces, and no error in the log?** `telemetry-endpoint` must be the host only. A full `/v1/traces` URL becomes `/v1/traces/v1/traces`, which 404s, and the exporter treats the 404 as a successful delivery. Logins keep working and nothing is logged. * **`First received frame was not SETTINGS` in the Keycloak log?** `telemetry-protocol` is unset, so the exporter is sending gRPC. Set it to `http/protobuf`. Note this is a `WARNING` on `io.quarkus`, so a production log level of `ERROR` hides it. * **`Installed features: [… opentelemetry …]` at startup does not mean tracing is on.** Quarkus lists its extension either way. The reliable local check is the log line format: with tracing enabled every line gains a `traceId=, parentId=, spanId=, sampled=` prefix. * **Everything disappeared after tuning the sampler.** `tracing-sampler-ratio=0.0` drops 100% of spans silently. So does `tracing-sampler-type=parentbased_traceidratio` when anything upstream — a proxy sampling at 10%, a frontend SDK — marks the request unsampled, because Keycloak honours incoming W3C trace context. The default `traceidratio` at ratio `1.0` ignores the upstream flag and is the safe setting. * **Span volume higher than expected?** One browser login is 48 server spans, 35 of which are login-theme CSS, fonts and images. There is no per-endpoint filter; `tracing-jdbc-enabled=false` will not help, since JDBC is only 9 of the 48. * **No span naming the hashing cost?** Only the Argon2 provider is instrumented. Under PBKDF2 you see `PasswordCredentialProvider.isValid` with an unexplained gap and no children. *** For assistance or questions, contact [support@bronto.io](mailto:support@bronto.io). # Kubernetes logs and metrics with OpenTelemetry Source: https://docs.bronto.io/integrations/kubernetes Deploy the OpenTelemetry Collector as a DaemonSet to collect Kubernetes pod logs, kubelet metrics, node events, and workload metadata. Collect pod logs and kubelet metrics across a Kubernetes cluster by running the OpenTelemetry Collector as a DaemonSet. The same Collector can receive application logs, metrics, and traces over OTLP. ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * A Kubernetes cluster with `kubectl` and Helm access * Pods writing to stdout/stderr (collected from `/var/log/pods` on each node) ## Deploy the Collector DaemonSet Install the Collector with the [OpenTelemetry Helm chart](https://github.com/open-telemetry/opentelemetry-helm-charts/tree/main/charts/opentelemetry-collector). Its `logsCollection` preset wires up the `filelog` receiver and node log mounts; the `kubernetesAttributes` preset adds pod, namespace, and node metadata and the RBAC it needs: ```yaml values.yaml theme={"dark"} mode: daemonset presets: logsCollection: enabled: true kubernetesAttributes: enabled: true kubeletMetrics: enabled: true config: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: x-bronto-collection: otlphttp/brontometrics: metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: exporters: [otlphttp/brontologs] metrics: exporters: [otlphttp/brontometrics] ``` ```bash theme={"dark"} helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts helm install otel-collector open-telemetry/opentelemetry-collector -f values.yaml ``` Set `` to `eu` or `us`. For logs, use `x-bronto-collection` to identify the cluster; Bronto infers per-workload log datasets from the Kubernetes metadata. Metrics appear in the Metric Explorer and do not belong to that collection or those datasets. Volume metrics, extra pod metadata, and request/limit utilization require the Collector service account to read the kubelet `/pods` endpoint through the `nodes/proxy` subresource. Add that RBAC permission if you enable those measurements. Use the Kubernetes or contrib Collector distribution because the core image does not include every Kubernetes receiver. For receiver settings, authentication, and available measurements, see the [Collector Contrib Kubelet Stats receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/kubeletstatsreceiver). ## Cluster events The DaemonSet above collects pod logs only. To also capture Kubernetes events (scheduling, image pulls, OOMKills, evictions), run a **second** Collector as a single-replica Deployment with the `kubernetesEvents` preset — it adds the `k8sobjects` receiver and the RBAC to watch events. Use a Deployment, not the DaemonSet, so events are not duplicated across nodes: ```yaml events-values.yaml theme={"dark"} mode: deployment replicaCount: 1 presets: kubernetesEvents: enabled: true config: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: x-bronto-collection: service: pipelines: logs: exporters: [otlphttp/brontologs] ``` ```bash theme={"dark"} helm install otel-events open-telemetry/opentelemetry-collector -f events-values.yaml ``` This needs a Collector image that bundles the `k8sobjects` receiver (the `k8s` or contrib distribution). Events arrive in Bronto as log records carrying the event reason, message, involved object, and namespace. ## What you will see in Bronto Open Search for pod logs and the Metric Explorer for kubelet metrics. Kubernetes resource attributes identify the pod, namespace, node, and container. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). This setup collects pod logs and kubelet metrics. To add distributed traces and RED metrics for your workloads without instrumenting them, deploy [OpenTelemetry eBPF Instrumentation](/opentelemetry/ebpf) as a DaemonSet alongside this Collector. ## Troubleshooting * **No logs?** Confirm the DaemonSet is running on every node (`kubectl get pods -l app.kubernetes.io/name=opentelemetry-collector`) and that nodes expose logs under `/var/log/pods`. * **Missing pod metadata?** The `kubernetesAttributes` preset creates the required RBAC by default — confirm it is enabled. * **Kubelet returns `403` for `/pods`?** Grant `get` on the `nodes/proxy` subresource. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit Fluent Bit is a long-established way to collect Kubernetes pod logs and a fine choice if your organization already runs it. Deploy it as a DaemonSet via the [official Helm chart](https://github.com/fluent/helm-charts): ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/containers/*.log multiline.parser docker, cri tag kube.* [FILTER] name kubernetes match kube.* k8s-logging.parser on k8s-logging.exclude on [OUTPUT] name http match kube.* host ingestion..bronto.io port 443 tls on format json_lines compress gzip header x-bronto-api-key header x-bronto-collection ``` Set **Format** to `json_lines`, not `json`. The `kubernetes` filter enriches each log with pod metadata, mirroring the `kubernetesAttributes` preset. Fluent Bit does not collect cluster events — use the OpenTelemetry Collector for those. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit) for details. # Send LangChain traces to Bronto via OpenTelemetry Source: https://docs.bronto.io/integrations/langchain Instrument LangChain applications with OpenTelemetry and send their traces to Bronto, with an optional path for existing LangSmith users. LangChain applications can send chain, agent, tool, and model-call traces to Bronto through OpenTelemetry. You do not need a LangSmith account: instrument LangChain with OpenLLMetry and use your existing OTel export pipeline. Already using the LangSmith SDK for tracing? Its OTel mode can route those traces through the same pipeline instead. [LangSmith](https://www.langchain.com/langsmith) is a separate observability product from LangChain and is optional for this setup. This page was verified on **July 17, 2026**. GenAI libraries and semantic conventions are evolving rapidly, so package configuration and emitted attributes can change between releases. Keep your instrumentation current and verify the fields emitted by the version you deploy. ## Prerequisites * Python 3.10+ or Node.js * An OTel SDK configured using [Python](/opentelemetry/python) or [Node.js](/opentelemetry/nodejs) * An LLM provider API key, such as OpenAI or Anthropic * An OTel Collector configured using [Connect OpenTelemetry to Bronto](/agent-setup/open-telemetry), or a direct OTLP trace exporter ## Instrument LangChain OpenLLMetry provides automatic LangChain instrumentation as part of its broader provider and framework coverage. Use the [OpenLLMetry integration guide](/integrations/openllmetry) to choose the bundled SDK or individual instrumentation package, configure content capture, and connect it to your existing OTel provider. Do not enable two instrumentations for the same model client. If OpenLLMetry instruments the underlying OpenAI, Anthropic, or Bedrock call, disable any overlapping provider instrumentation to avoid duplicate spans. The LangChain instrumentation can add spans for framework operations such as chains, agents, and tools. Model-call attributes come from the corresponding provider instrumentation, so their presence depends on the provider, package, and version. ## What you get A LangChain trace can contain: * Parent spans representing chains, agents, tools, or other framework operations * Child spans for calls to instrumented model providers * Request and response content when content capture is enabled * Token usage, model metadata, finish reasons, and request parameters when the provider reports them For provider spans that implement the current OTel GenAI convention, use fields such as `gen_ai.provider.name`, `gen_ai.operation.name`, `gen_ai.request.model`, and `gen_ai.usage.input_tokens` / `gen_ai.usage.output_tokens`. See [LLM Observability](/ai-features/llm-observability#3-know-what-youll-see) for the standard field definitions and query examples. Framework spans do not necessarily use the same schema as provider spans. Depending on the OpenLLMetry release, LangChain workflow, task, agent, or tool spans may include `traceloop.*` compatibility attributes. Inspect an emitted trace before building dashboards that depend on framework-specific fields. ## Optional: route existing LangSmith traces to Bronto Use this option only if your application already relies on LangSmith tracing or its `traceable` API. LangSmith's current tracing modes can send those traces to LangSmith, an OTel backend, or both. Configure your OTel `TracerProvider` and exporter before importing LangChain or LangSmith components. Then select OTel-only routing: ```bash theme={"dark"} export LANGSMITH_TRACING=true export LANGSMITH_TRACING_MODE=otel ``` Install the current SDK for your language: ```bash theme={"dark"} pip install --upgrade "langsmith[otel]" ``` The equivalent programmatic configuration is `Client(tracing_mode="otel")`. ```bash theme={"dark"} npm install langsmith@latest ``` The equivalent programmatic configuration is `new Client({ tracingMode: "otel" })`. In OTel mode, LangSmith-created spans use the configured OTel provider and export pipeline. They can contain `langsmith.*` attributes in addition to any standard `gen_ai.*` fields. If you want traces in both LangSmith and Bronto, use LangSmith's hybrid or replica routing rather than OTel-only mode; see the [current LangSmith routing documentation](https://docs.langchain.com/langsmith/log-traces-to-project#route-between-langsmith-and-opentelemetry-destinations). ## Send traces to Bronto **Via a Collector** — point the application's OTLP trace exporter at the Collector, then configure the Collector using [Connect OpenTelemetry to Bronto](/agent-setup/open-telemetry). This is recommended in production. **Direct export** — point the trace exporter at the Bronto ingestion endpoint and add your API key: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://ingestion.eu.bronto.io/v1/traces" export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf" export OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=" ``` | Region | Traces endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io/v1/traces` | | US | `https://ingestion.us.bronto.io/v1/traces` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. ## Verify in Bronto Open [Log Search](https://app.bronto.io/search) and filter by the `service.name` configured on your OTel resource. To find instrumented model calls that report token usage: ```sql theme={"dark"} "$gen_ai.usage.input_tokens" > 0 ``` Group `$gen_ai.usage.input_tokens` or `$gen_ai.usage.output_tokens` by `$gen_ai.provider.name` to compare usage across the providers called by your LangChain application. See [LLM Observability](/ai-features/llm-observability#4-search-and-aggregate) for aggregation examples. If no traces appear, check that instrumentation is initialized before LangChain and the provider SDKs are imported, verify the OTLP endpoint and API-key header, and ensure short-lived processes flush their span processor before exit. ## References * [OpenLLMetry](/integrations/openllmetry) * [Python: GenAI semantic conventions](/opentelemetry/python#genai-semantic-conventions) * [Node.js: GenAI semantic conventions](/opentelemetry/nodejs#genai-semantic-conventions) * [LLM Observability](/ai-features/llm-observability) * [LangSmith OTel tracing](https://docs.langchain.com/langsmith/trace-with-opentelemetry) * [LangSmith tracing modes](https://docs.langchain.com/langsmith/log-traces-to-project#route-between-langsmith-and-opentelemetry-destinations) # MongoDB logs and metrics with OpenTelemetry Source: https://docs.bronto.io/integrations/mongodb Collect self-hosted MongoDB server logs and database metrics — slow queries, connections, and replication — with the OpenTelemetry Collector. Collect logs from a self-hosted MongoDB server — connections, slow queries, replication, and errors — with the OpenTelemetry Collector. The same Collector can also forward traces and metrics from your apps — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * MongoDB writing logs to a file (`systemLog.destination: file`). The default path is `/var/log/mongodb/mongod.log` * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) installed on the same host ## Configure the Collector MongoDB 4.4+ writes one structured JSON object per line. Parse it with the `json_parser` operator: ```yaml /etc/otel/config.yaml theme={"dark"} receivers: filelog/mongodb: include: - /var/log/mongodb/mongod.log operators: - type: json_parser resource: service.name: mongodb service.namespace: processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/mongodb] processors: [batch] exporters: [otlphttp/brontologs] ``` Set `` to `eu` or `us`. ## Metrics The Collector Contrib `mongodb` receiver collects operation, connection, memory, cache, replication, and database metrics: ```yaml theme={"dark"} receivers: mongodb: hosts: - endpoint: localhost:27017 username: password: collection_interval: 30s ``` Add this receiver to the [Bronto metrics pipeline](/metrics/send-metrics). Use a monitoring user and check the [Collector Contrib MongoDB receiver documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/mongodbreceiver) for authentication options and measurements available from your MongoDB version. ## What you will see in Bronto Open [Search](https://app.bronto.io/search) and filter by `service.name = mongodb`. Each entry carries a timestamp (`t`), severity (`s`), component (`c` — e.g. `NETWORK`, `QUERY`, `REPL`), context (`ctx`), and message (`msg`); slow operations include the command, namespace, and `durationMillis` under `attr`. The `json_parser` promotes these to searchable fields. ## Troubleshooting * **Older MongoDB (pre-4.4)** writes plain text, not JSON. Drop the `json_parser` operator and let Bronto's [Custom Parser](/core-features/custom-parser) extract fields server-side. * **Log volume:** raising `systemLog.verbosity` greatly increases output — keep it low in production. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit If you already run Fluent Bit, tail the MongoDB log file and forward it over HTTP: ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/mongodb/mongod.log tag mongodb [OUTPUT] name http match mongodb host ingestion..bronto.io port 443 tls on format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset mongodb header x-bronto-collection ``` Set **Format** to `json_lines`, not `json`. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit) for installation. # MySQL logs and metrics with OpenTelemetry Source: https://docs.bronto.io/integrations/mysql Collect self-hosted MySQL error and slow query logs plus database metrics with the OpenTelemetry Collector to debug slow queries and locking in Bronto. Collect logs from a self-hosted MySQL server — the error log and the slow query log — with the OpenTelemetry Collector. The same Collector can also forward traces and metrics from your apps — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * MySQL writing logs to disk. The default error log on Debian/Ubuntu is `/var/log/mysql/error.log` * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) installed on the same host Enable the slow query log in `my.cnf` to capture queries worth investigating: ```ini my.cnf theme={"dark"} [mysqld] slow_query_log = 1 slow_query_log_file = /var/log/mysql/mysql-slow.log long_query_time = 1 ``` ## Configure the Collector Error and slow-query entries can span multiple lines. Use `multiline` keyed on the leading timestamp or the slow-log `# Time:` header: ```yaml /etc/otel/config.yaml theme={"dark"} receivers: filelog/mysql: include: - /var/log/mysql/error.log - /var/log/mysql/mysql-slow.log multiline: line_start_pattern: '^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}|# Time:)' resource: service.name: mysql service.namespace: processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/mysql] processors: [batch] exporters: [otlphttp/brontologs] ``` Set `` to `eu` or `us`. ## Metrics The Collector Contrib `mysql` receiver collects connection, command, handler, query, buffer-pool, and replication metrics: ```yaml theme={"dark"} receivers: mysql: endpoint: localhost:3306 username: password: collection_interval: 30s ``` Add this receiver to the [Bronto metrics pipeline](/metrics/send-metrics). Use a least-privilege monitoring account and check the [Collector Contrib MySQL receiver documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/mysqlreceiver) for measurements that depend on your MySQL version. ## What you will see in Bronto Open [Search](https://app.bronto.io/search) and filter by `service.name = mysql`. The error log carries startup/shutdown, errors, and warnings (timestamp, thread ID, severity, subsystem); the slow query log carries each slow statement with `Query_time`, `Lock_time`, `Rows_examined`, and the SQL text. Bronto's [Custom Parser](/core-features/custom-parser) extracts these fields server-side. ## Troubleshooting * **Where are the logs?** Run `SHOW VARIABLES LIKE 'log_error';` and `SHOW VARIABLES LIKE 'slow_query_log_file';`. Adjust the `include` paths to match. * **General query log:** disabled by default and very verbose — enable (`general_log = 1`) only for short debugging sessions. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit If you already run Fluent Bit, tail the MySQL log files and forward them over HTTP: ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/mysql/error.log,/var/log/mysql/mysql-slow.log tag mysql [OUTPUT] name http match mysql host ingestion..bronto.io port 443 tls on format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset mysql header x-bronto-collection ``` Set **Format** to `json_lines`, not `json`. For slow-query entries that span lines, add a `multiline.parser` keyed on the `# Time:` header. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit). # Nginx logs, metrics, and traces with OpenTelemetry Source: https://docs.bronto.io/integrations/nginx Collect Nginx access logs, error logs, stub_status metrics, and request traces with the OpenTelemetry Collector and forward all three signals to Bronto. Forward Nginx access and error logs, and optionally request traces, to Bronto through a single OpenTelemetry Collector. See [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) for Collector basics. ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * Nginx running and writing logs (default paths: `/var/log/nginx/access.log` and `/var/log/nginx/error.log`) * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) installed on the same host * For traces: Nginx 1.25.3+ with the [`ngx_otel_module`](https://nginx.org/en/docs/ngx_otel_module.html) (install the `nginx-module-otel` package) ## Logs, metrics, and traces Nginx emits request traces over OTLP/gRPC through `ngx_otel_module` and exposes connection/request metrics through `stub_status`. The example uses the standard same-host OTLP/gRPC endpoint, `localhost:4317`. Change the host, port, and TLS settings when the Collector is not local or its receiver configuration differs. **1. Enable tracing in Nginx.** Add `load_module` to the top of `nginx.conf` and the `otel_*` directives inside the `http` block: ```nginx nginx.conf theme={"dark"} load_module modules/ngx_otel_module.so; http { otel_exporter { endpoint localhost:4317; } otel_service_name nginx; otel_trace on; otel_trace_context propagate; server { listen 127.0.0.1:8080; location /status { stub_status; allow 127.0.0.1; deny all; } } } ``` **2. Configure the Collector** to tail the log files and accept traces, then export each signal to Bronto: ```yaml /etc/otel/config.yaml theme={"dark"} receivers: filelog/nginx: include: - /var/log/nginx/access.log - /var/log/nginx/error.log resource: service.name: nginx service.namespace: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 nginx: endpoint: http://localhost:8080/status collection_interval: 30s processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: otlphttp/brontometrics: metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" compression: gzip headers: x-bronto-api-key: otlphttp/brontotraces: traces_endpoint: "https://ingestion..bronto.io/v1/traces" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/nginx] processors: [batch] exporters: [otlphttp/brontologs] metrics: receivers: [nginx] processors: [batch] exporters: [otlphttp/brontometrics] traces: receivers: [otlp] processors: [batch] exporters: [otlphttp/brontotraces] ``` Set `` to `eu` or `us`. For logs, the `service.name` / `service.namespace` attributes (and `otel_service_name`) select the Bronto dataset and collection. Metrics and traces keep the same service identity but appear only in the Metric Explorer and Explore Traces, not in datasets or collections. You can remove any signal pipeline you do not need. For receiver options and available measurements, see the [Collector Contrib NGINX receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/nginxreceiver). ## What you will see in Bronto Open [Search](https://app.bronto.io/search) and filter by `service.name = nginx`. Access logs in the default `combined` format carry the client IP, request method and path, HTTP status code, response size, referrer, and user agent; error logs carry a timestamp, severity level (`error`, `warn`, `crit`), and the message. Bronto's [Custom Parser](/core-features/custom-parser) extracts these fields server-side — no parser operators needed in the Collector. Traces appear in [Explore Traces](/tracing/explore-traces) — one span per request, with the method, route, status code, and duration. See [Send Traces to Bronto](/tracing/send-traces) for more. ## Troubleshooting * **No logs?** Confirm the Collector's user can read `/var/log/nginx/`. Run `sudo chmod +r /var/log/nginx/*.log` or add the user to the `adm` group, then restart the Collector. * **No traces?** Confirm `ngx_otel_module` is loaded (`nginx -V`), `otel_trace` is `on`, and the `otel_exporter` endpoint matches the Collector's configured OTLP/gRPC receiver address. * **Want structured fields at the source?** Switch Nginx to a JSON `log_format` (see the [Nginx log\_format reference](https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format)) for direct field extraction. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit If your organization already runs Fluent Bit, forward the Nginx log files with its `tail` input and HTTP output. Fluent Bit handles logs only — for traces, use the OpenTelemetry Collector above. ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/nginx/access.log,/var/log/nginx/error.log tag nginx [OUTPUT] name http match nginx host ingestion..bronto.io port 443 tls on format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset nginx header x-bronto-collection ``` Set **Format** to `json_lines`, not `json` — `json` sends a single array and breaks ingestion. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit) for installation and the full output reference. # Send Okta events to Bronto Source: https://docs.bronto.io/integrations/okta Stream all Okta System Log events to Bronto through AWS EventBridge Log Streaming — no Lambda, no middleware, and no verification handshake required. ## Overview Okta's Log Streaming feature pushes every System Log event to AWS EventBridge in near real time. From there, an EventBridge API Destination forwards them directly to Bronto — no Lambda function, no verification handshake, and no middleware required. This is the recommended approach for sending Okta events to Bronto. Okta Event Hooks are not a good fit for this direct integration because they require a verification payload exchange that Bronto ingestion endpoints do not support. To use Event Hooks, you would need to place a proxy service in front of Bronto to handle the verification step and then forward the events. ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys)) * An AWS account with permissions to configure EventBridge * Super admin access to your Okta org * Okta Log Streaming is available on Okta's **Enterprise** plan. Contact Okta support to confirm it is enabled for your org. *** ## How it works ```text theme={"dark"} Okta System Log → AWS EventBridge (partner event bus) → EventBridge Rule → API Destination → Bronto ``` Okta sends all System Log events to a dedicated EventBridge partner event bus. An EventBridge rule matches those events and routes them to a Bronto API Destination, which POSTs them to Bronto's ingestion endpoint with your API key and routing headers attached. *** ## Step 1 — Add the AWS EventBridge log stream in Okta 1. In the Okta Admin Console, go to **Reports → Log Streaming**. 2. Click **Add Log Stream** and select **AWS EventBridge**. 3. Fill in the configuration: | Field | Value | | - | - | | Name | `Bronto` | | AWS Event Source Name | `okta-bronto` (no spaces or special characters) | | AWS Account ID | Your 12-digit AWS account ID | | AWS Region | Select the region closest to your Bronto region | 4. Click **Save**. The stream appears as **Active** on the Log Streaming page. Okta streams **all** System Log events — there is no event filtering available on the Okta side. Filtering can be applied at the EventBridge rule level if needed. For full details, see the [Okta Log Streaming documentation](https://help.okta.com/en-us/content/topics/reports/log-streaming/add-aws-eb-log-stream.htm). *** ## Step 2 — Activate the partner event bus in AWS 1. In the AWS Console, go to **Amazon EventBridge → Partner event sources**. 2. Find the pending event source — it will be named in the format: ```text theme={"dark"} aws.partner/okta.com//okta-bronto ``` 3. Select it and click **Associate with an event bus**. 4. Set the required permissions and click **Associate**. The status changes to **Active**. *** ## Step 3 — Create a Bronto connection in EventBridge The connection stores your Bronto API key and routing headers. In **EventBridge → API Destinations → Connections → Create connection**: | Field | Value | | - | - | | Connection name | `bronto-connection` | | Authorization type | `API Key` | | API key name | `x-bronto-api-key` | | API key value | `` | The `x-bronto-dataset` and `x-bronto-collection` headers are added at the **API destination** level, not the connection level. You will set these in Step 4 via the Invocation Http Parameters section in the console. Alternatively, you can set them on the connection via the AWS CLI: ```bash theme={"dark"} aws events update-connection \ --name bronto-connection \ --auth-parameters '{ "ApiKeyAuthParameters": { "ApiKeyName": "x-bronto-api-key", "ApiKeyValue": "" }, "InvocationHttpParameters": { "HeaderParameters": [ { "Key": "x-bronto-dataset", "Value": "Okta", "IsValueSecret": false }, { "Key": "x-bronto-collection", "Value": "", "IsValueSecret": false } ] } }' ``` *** ## Step 4 — Create a Bronto API destination In **EventBridge → API Destinations → Create API destination**: | Field | Value | | - | - | | Name | `bronto-destination` | | API destination endpoint | `https://ingestion.eu.bronto.io` (or `us`) | | HTTP method | `POST` | | Connection | `bronto-connection` | Expand **Invocation Http Parameters** and add two header parameters: | Parameter name | Key | Value | | - | - | - | | Header | `x-bronto-dataset` | `Okta` | | Header | `x-bronto-collection` | `` | Use the base endpoint `https://ingestion.eu.bronto.io` with no path. Do not append `/v1/logs` — that path accepts only OTLP protobuf. EventBridge sends JSON and must target the base endpoint. *** ## Step 5 — Create an EventBridge rule The rule must be created on the **Okta partner event bus**, not the default event bus. Rules on the default bus will not receive Okta events. 1. In **EventBridge → Rules**, change the event bus dropdown from `default` to `aws.partner/okta.com//okta-bronto`. 2. Click **Create rule**. 3. Give the rule a name, e.g. `okta-to-bronto`. 4. Select **Advanced builder** (top left) for step-by-step configuration. 5. On the **Build event pattern** step, select **Custom pattern (JSON editor)** and paste: ```json theme={"dark"} { "source": [{ "prefix": "aws.partner/okta.com" }], "detail-type": ["SystemLog"] } ``` 6. On the **Select target(s)** step, set: * Target type: **EventBridge API destination** * Select **Use an existing API destination** → `bronto-destination` * Execution role: **Create a new role for this specific resource** (default) 7. Click through to **Review and create**. A common mistake is creating the rule on the `default` event bus. Always confirm the event bus shown at the top of the Rules page matches your Okta partner event bus name before creating the rule. *** ## Verify in Bronto Open Bronto and go to [Search](https://app.bronto.io/search). Trigger a test event, for example by signing in or out of the Okta Admin Console, and confirm the event appears in the UI. Each event arrives as a full Okta System Log record nested inside an EventBridge envelope. The Okta event payload is in the `detail` object. *** ## What you will see in Bronto Okta events arrive wrapped in the EventBridge event structure. The Okta System Log payload is in the `detail` field. Useful fields in Bronto include: * `detail.eventType`, for example `user.session.start` * `detail.actor.alternateId`, identifying who triggered the event * `detail.outcome.result`, showing success or failure * `detail.published`, the event timestamp * `detail.severity` Common filters include: * `detail.eventType` * `detail.actor.alternateId` * `detail.severity` *** ## Troubleshooting * **No events appearing in Bronto?** Confirm the Okta log stream shows as **Active** under **Reports → Log Streaming** and that the EventBridge partner event source is **Associated** in the AWS console. * **Rule shows no invocations?** Check that the rule is on the **Okta partner event bus**, not the `default` event bus. Go to **EventBridge → Rules**, switch the bus dropdown to `aws.partner/okta.com//okta-bronto`, and confirm your rule appears there. Rules on the default bus will never receive Okta events. * **Getting 401 errors?** Verify the `x-bronto-api-key` value in the EventBridge connection matches a valid Bronto API key with the Ingestion role. * **Events arriving without a dataset or collection?** Confirm the `x-bronto-dataset` and `x-bronto-collection` header parameters are set in the Invocation Http Parameters section of the `bronto-destination` API destination. * **Partner event source stuck in Pending?** The source only becomes active after you associate it with an event bus in the AWS console — see Step 2. * **Log Streaming not available in Okta?** This feature requires the Okta Enterprise plan. Contact Okta support to enable it for your org. # Send OpenLLMetry traces to Bronto Source: https://docs.bronto.io/integrations/openllmetry Instrument LLM providers, agent frameworks, and vector databases with Traceloop OpenLLMetry and send the resulting OpenTelemetry traces to Bronto. [OpenLLMetry](https://github.com/traceloop/openllmetry) is a collection of OpenTelemetry instrumentations maintained by Traceloop. It adds tracing for LLM provider SDKs, agent frameworks, and vector databases that may not be covered by the official OpenTelemetry contrib packages. Use OpenLLMetry when you need broader automatic coverage—for example, Anthropic instrumentation in Node.js—or want framework-level workflow and task spans. If an official OTel contrib instrumentation covers your provider, prefer it for the most direct alignment with the latest [OTel GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai). OpenLLMetry is built on OpenTelemetry, but attribute coverage varies by language, instrumentation, and release. Current JavaScript provider instrumentations use current fields such as `gen_ai.provider.name`, `gen_ai.operation.name`, and `gen_ai.usage.input_tokens` / `gen_ai.usage.output_tokens`. Older releases and some Python, framework, workflow, or task spans may also emit legacy or `traceloop.*` attributes. Keep OpenLLMetry updated and verify the fields emitted by the version you deploy. ## Prerequisites * A Bronto API key with ingestion permissions—see [API Keys](/Account-Management/API-Keys) * An application that uses a supported LLM provider or framework * Python or Node.js; see OpenLLMetry's [current support matrix](https://docs.traceloop.com/docs/openllmetry/tracing/supported) before choosing an instrumentation * Optional: an OTel Collector configured using [Connect OpenTelemetry to Bronto](/agent-setup/open-telemetry) ## Choose an integration approach OpenLLMetry provides a bundled SDK and individual instrumentation packages: * Use the **bundled SDK** for the simplest setup. It detects supported libraries and configures tracing and export. * Use **individual instrumentations** when your application already owns its OTel `TracerProvider`, processors, and exporters. This avoids creating a second provider and lets OpenLLMetry spans follow your existing sampling and export configuration. Do not enable two instrumentations for the same provider call. For example, choose either the OTel contrib OpenAI instrumentation or OpenLLMetry's OpenAI instrumentation, otherwise a single request can produce duplicate spans. ## Node.js Install the bundled SDK: ```bash theme={"dark"} npm install @traceloop/node-server-sdk ``` Initialize it before importing any LLM provider or framework module so that OpenLLMetry can patch the module as it loads: ```ts theme={"dark"} import * as traceloop from "@traceloop/node-server-sdk"; traceloop.initialize({ appName: "llm-service" }); // Import provider SDKs only after OpenLLMetry is initialized. const { Anthropic } = await import("@anthropic-ai/sdk"); ``` If you already manage the OTel SDK, install only the provider instrumentation you need. For example: ```bash theme={"dark"} npm install @traceloop/instrumentation-anthropic ``` Register it with the same `NodeSDK` or `registerInstrumentations` configuration as your other OTel instrumentations. See [Node.js: GenAI semantic conventions](/opentelemetry/nodejs#genai-semantic-conventions) for the shared SDK setup. ## Python Install and initialize the bundled SDK before making provider calls: ```bash theme={"dark"} pip install --upgrade traceloop-sdk ``` ```python theme={"dark"} from traceloop.sdk import Traceloop Traceloop.init(app_name="llm-service") ``` OpenLLMetry also publishes individual `opentelemetry-instrumentation-*` packages. If your application already configures a global OTel `TracerProvider`, use the individual package and the normal OTel auto-instrumentation flow instead of initializing a second SDK. See [Python: GenAI semantic conventions](/opentelemetry/python#genai-semantic-conventions). ## Send traces to Bronto ### Through an OTel Collector Point OpenLLMetry at the Collector's OTLP/HTTP receiver. `TRACELOOP_BASE_URL` is a base endpoint; OpenLLMetry appends `/v1/traces`: ```bash theme={"dark"} export TRACELOOP_BASE_URL="http://localhost:4318" ``` `http://localhost:4318` is the standard local OTLP/HTTP default. Replace it with the Collector address reachable from the application when the Collector runs elsewhere or uses different port, protocol, or TLS settings. Configure the Collector to forward traces to Bronto as described in [Connect OpenTelemetry to Bronto](/agent-setup/open-telemetry). The Collector is recommended in production because it centralizes credentials, batching, sampling, retries, and fan-out. ### Directly to Bronto Set the Bronto ingestion base URL and API-key header. Do not include `/v1/traces` in `TRACELOOP_BASE_URL` because OpenLLMetry adds it automatically. ```bash theme={"dark"} export TRACELOOP_BASE_URL="https://ingestion.eu.bronto.io" export TRACELOOP_HEADERS="x-bronto-api-key=" ``` ```bash theme={"dark"} export TRACELOOP_BASE_URL="https://ingestion.us.bronto.io" export TRACELOOP_HEADERS="x-bronto-api-key=" ``` `TRACELOOP_HEADERS` is required because Bronto authenticates with `x-bronto-api-key`; `TRACELOOP_API_KEY` sends a bearer token and is intended for the Traceloop service. ## Control prompt and response capture OpenLLMetry captures prompts, completions, and embeddings on spans **by default**. These values may contain personal data, credentials, proprietary context, or large payloads. Disable content capture globally unless you have intentionally approved collecting it: ```bash theme={"dark"} export TRACELOOP_TRACE_CONTENT=false ``` In Node.js you can instead configure `traceContent: false`: ```ts theme={"dark"} traceloop.initialize({ appName: "llm-service", traceContent: false, }); ``` This setting does not remove model metadata or token usage. It suppresses prompt, response, and embedding content collected by OpenLLMetry instrumentations. ## What you get On current provider spans, query the OTel GenAI semantic-convention attributes that the provider response makes available: | Attribute | What it represents | | - | - | | `gen_ai.provider.name` | Model provider, such as `anthropic` or `openai` | | `gen_ai.operation.name` | Operation type, such as `chat` or `text_completion` | | `gen_ai.request.model` / `gen_ai.response.model` | Requested and returned model names | | `gen_ai.request.max_tokens` | Configured output-token limit | | `gen_ai.request.temperature` / `gen_ai.request.top_p` | Sampling parameters | | `gen_ai.response.finish_reasons` | Reasons generation stopped | | `gen_ai.usage.input_tokens` / `gen_ai.usage.output_tokens` | Input and output token counts | | `gen_ai.usage.cache_read.input_tokens` / `gen_ai.usage.cache_creation.input_tokens` | Prompt-cache token counts, when reported | | `gen_ai.system_instructions` | System instructions, when content capture is enabled | | `gen_ai.input.messages` / `gen_ai.output.messages` | Structured messages, when content capture is enabled | OpenLLMetry may add fields outside this list, including `gen_ai.usage.total_tokens`, provider-specific extensions, and `traceloop.*` workflow or task attributes. These can be useful, but they are not a portable substitute for the current OTel fields above. ## Verify in Bronto Open [Log Search](https://app.bronto.io/search) and filter on the service name or standard GenAI fields. For example, find Anthropic calls with token usage: ```sql theme={"dark"} "$gen_ai.provider.name" = 'anthropic' AND "$gen_ai.usage.input_tokens" > 0 ``` To compare usage across providers, create a visualization using **Sum**, **Median**, or **P75**, **P90**, **P95**, or **P99** on `$gen_ai.usage.input_tokens` or `$gen_ai.usage.output_tokens`, grouped by `$gen_ai.provider.name`. See [LLM Observability](/ai-features/llm-observability#4-search-and-aggregate) for the complete query and aggregation examples. ## Troubleshooting * **No Node.js provider spans:** initialize OpenLLMetry before importing the provider SDK. Module patching cannot instrument an SDK that was loaded first. * **Duplicate model spans:** disable the overlapping contrib or OpenLLMetry instrumentation so only one package instruments each provider. * **No traces after a short-lived script exits:** temporarily use `disableBatch: true` in Node.js or `disable_batch=True` in Python while testing, or shut down the SDK cleanly before exit. * **404 from direct export:** remove `/v1/traces` from `TRACELOOP_BASE_URL`; OpenLLMetry appends the signal path. * **Queries do not match:** inspect a span from the installed package. Upgrade older OpenLLMetry releases and base shared dashboards on the current `gen_ai.*` fields listed above. ## References * [OpenLLMetry Python repository](https://github.com/traceloop/openllmetry) * [OpenLLMetry-JS repository](https://github.com/traceloop/openllmetry-js) * [OpenLLMetry initialization options](https://docs.traceloop.com/docs/openllmetry/configuration) * [OpenLLMetry content-capture controls](https://docs.traceloop.com/docs/openllmetry/privacy/traces) * [OpenTelemetry GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai) * [LLM Observability](/ai-features/llm-observability) # PagerDuty Source: https://docs.bronto.io/integrations/pagerduty Forward PagerDuty incident events into Bronto with PagerDuty's Generic Webhooks integration to search and analyze them alongside your other telemetry. ## Overview PagerDuty supports delivering event data to third-party systems using its **Generic Webhooks** integration. This guide walks you through configuring PagerDuty to forward PagerDuty events into Bronto for storage and analysis. PagerDuty webhooks can be configured at different scopes and allow you to subscribe to specific event types. For detailed information on PagerDuty webhooks, scopes, and available event types, refer to the [official PagerDuty documentation](https://support.pagerduty.com/main/docs/webhooks). Once configured, PagerDuty will send event payloads via HTTPS to Bronto’s ingestion endpoint. ## PagerDuty Webhook Configuration 1. Create a Generic Webhook in PagerDuty. 2. Choose the desired scope and event types. Refer to the [PagerDuty documentation](https://support.pagerduty.com/main/docs/webhooks) for details. Configure the webhook with destination URL: ``` https://ingestion..bronto.io/ ``` The `` refers to your data storage region, e.g., "eu", "us". 3. Custom Headers Add the following custom headers to the webhook: * `x-bronto-api-key`- your Bronto API key. *Tip: It is recommended to create a dedicated API key for PagerDuty with **ingestion-only** permissions. See the [Bronto API Keys documentation](/Account-Management/API-Keys) for details.* * `x-bronto-dataset` - target dataset name in Bronto. (*Does not need to pre-exist* in Bronto. It will be automatically created when events are ingested.) * `x-bronto-collection` - target collection name in Bronto. (*Does not need to pre-exist* in Bronto. It will be automatically created when events are ingested.) * `x-bronto-tags` (optional) - `` ## Testing the Integration After saving the webhook, click Send Test Event in PagerDuty. The event should appear in Bronto under the specified dataset within a few seconds to a few minutes. ## Screenshots # PostgreSQL logs and metrics with OpenTelemetry Source: https://docs.bronto.io/integrations/postgresql Collect self-hosted PostgreSQL logs and database metrics — errors, slow queries, and connection activity — with the OpenTelemetry Collector. Collect logs from a self-hosted PostgreSQL server — errors, slow queries, and connection activity — with the OpenTelemetry Collector. The same Collector can also forward traces and metrics from your apps — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * PostgreSQL writing logs to disk. The default `log_directory` lives under the data directory; Debian/Ubuntu packages use `/var/log/postgresql/` * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) installed on the same host To capture useful detail, set these in `postgresql.conf` and reload: ```ini postgresql.conf theme={"dark"} logging_collector = on log_min_duration_statement = 1000 # log statements slower than 1s log_connections = on log_disconnections = on ``` ## Configure the Collector PostgreSQL entries can span multiple lines (statements, context). Use `multiline` keyed on the leading timestamp: ```yaml /etc/otel/config.yaml theme={"dark"} receivers: filelog/postgresql: include: - /var/log/postgresql/*.log multiline: line_start_pattern: '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}' resource: service.name: postgresql service.namespace: processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/postgresql] processors: [batch] exporters: [otlphttp/brontologs] ``` Set `` to `eu` or `us`. ## Metrics The Collector Contrib `postgresql` receiver collects database size, connection, transaction, block, row, and replication metrics through a read-only database connection: ```yaml theme={"dark"} receivers: postgresql: endpoint: localhost:5432 transport: tcp username: password: databases: [postgres] collection_interval: 30s ``` Add this receiver to the [Bronto metrics pipeline](/metrics/send-metrics). Check the [Collector Contrib PostgreSQL receiver documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/postgresqlreceiver) for permissions and measurements available in your PostgreSQL and Collector versions. ## What you will see in Bronto Open [Search](https://app.bronto.io/search) and filter by `service.name = postgresql`. Entries include slow-query lines (with duration and statement text), connection and disconnection events, errors, and warnings — each prefixed with a timestamp, process ID, and severity. Bronto's [Custom Parser](/core-features/custom-parser) extracts these fields server-side. ## Troubleshooting * **Where are the logs?** Run `SHOW log_directory;` and `SHOW log_filename;` in `psql`, or read `$PGDATA/current_logfiles`. Adjust the `include` path to match. * **Want structured fields at the source?** On PostgreSQL 15+, set `log_destination = 'jsonlog'` for JSON log files (`*.json`) and point `include` at them for direct field extraction. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit If you already run Fluent Bit, tail the PostgreSQL log files and forward them over HTTP: ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/postgresql/*.log tag postgresql [OUTPUT] name http match postgresql host ingestion..bronto.io port 443 tls on format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset postgresql header x-bronto-collection ``` Set **Format** to `json_lines`, not `json`. For statements that span lines, add a `multiline.parser` keyed on the leading timestamp. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit). # RabbitMQ logs and metrics with OpenTelemetry Source: https://docs.bronto.io/integrations/rabbitmq Collect self-hosted RabbitMQ broker logs and queue metrics — connections, channel activity, and node events — with the OpenTelemetry Collector. Collect logs from a self-hosted RabbitMQ broker — connections, channel activity, node events, and errors — with the OpenTelemetry Collector. The same Collector can also forward traces and metrics from your apps — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * RabbitMQ writing logs to a file (default: `/var/log/rabbitmq/rabbit@.log`) * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) installed on the same host ## Configure the Collector RabbitMQ entries begin with a timestamp, and some span multiple lines (crash reports). Use `multiline` keyed on the leading timestamp: ```yaml /etc/otel/config.yaml theme={"dark"} receivers: filelog/rabbitmq: include: - /var/log/rabbitmq/*.log multiline: line_start_pattern: '^\d{4}-\d{2}-\d{2}' resource: service.name: rabbitmq service.namespace: processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/rabbitmq] processors: [batch] exporters: [otlphttp/brontologs] ``` Set `` to `eu` or `us`. ## Metrics Enable RabbitMQ's management plugin, then use the Collector Contrib `rabbitmq` receiver to collect node, queue, connection, channel, consumer, and message metrics: ```yaml theme={"dark"} receivers: rabbitmq: endpoint: http://localhost:15672 username: password: collection_interval: 30s ``` Add this receiver to the [Bronto metrics pipeline](/metrics/send-metrics). Metric availability depends on the RabbitMQ management API and Collector receiver versions; see the [Collector Contrib RabbitMQ receiver documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/rabbitmqreceiver). ## What you will see in Bronto Open [Search](https://app.bronto.io/search) and filter by `service.name = rabbitmq`. Each line carries a timestamp, log level (`[info]`, `[warning]`, `[error]`), the Erlang process id, and the message — connection open/close, channel errors, queue declarations, and node lifecycle events. Bronto's [Custom Parser](/core-features/custom-parser) extracts these fields server-side. ## Troubleshooting * **Want structured fields at the source?** RabbitMQ's default format is plain text. For JSON logs (RabbitMQ 3.9+), set `log.file.formatter = json` in `rabbitmq.conf`, then add a `json_parser` operator to the receiver. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit If you already run Fluent Bit, tail the RabbitMQ log file and forward it over HTTP: ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/rabbitmq/*.log tag rabbitmq [OUTPUT] name http match rabbitmq host ingestion..bronto.io port 443 tls on format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset rabbitmq header x-bronto-collection ``` Set **Format** to `json_lines`, not `json`. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit) for installation. # Redis logs and metrics with OpenTelemetry Source: https://docs.bronto.io/integrations/redis Collect self-hosted Redis server logs and cache metrics — slow log entries, replication events, and memory use — with the OpenTelemetry Collector. Collect logs from a self-hosted Redis server with the OpenTelemetry Collector. The same Collector can also forward traces and metrics from your apps — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * Redis configured to log to a file. By default `logfile` is empty (Redis logs to stdout); set it in `redis.conf` * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) installed on the same host ```ini redis.conf theme={"dark"} logfile /var/log/redis/redis-server.log loglevel notice ``` ## Configure the Collector Redis writes one entry per line, so no multiline handling is needed: ```yaml /etc/otel/config.yaml theme={"dark"} receivers: filelog/redis: include: - /var/log/redis/redis-server.log resource: service.name: redis service.namespace: processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/redis] processors: [batch] exporters: [otlphttp/brontologs] ``` Set `` to `eu` or `us`. ## Metrics The Collector Contrib `redis` receiver reads Redis `INFO` data for memory, clients, commands, keyspace, persistence, and replication metrics: ```yaml theme={"dark"} receivers: redis: endpoint: localhost:6379 password: collection_interval: 30s ``` Add this receiver to the [Bronto metrics pipeline](/metrics/send-metrics). Check the [Collector Contrib Redis receiver documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/redisreceiver) for measurements available in your Redis and Collector versions. ## What you will see in Bronto Open [Search](https://app.bronto.io/search) and filter by `service.name = redis`. Each line carries the process role indicator (e.g. `M` master, `S` replica, `C` child), a timestamp, a level symbol, and the message — startup, configuration warnings, RDB/AOF persistence, replication, and client events. Bronto's [Custom Parser](/core-features/custom-parser) extracts these fields server-side. Redis's slow-command log (`SLOWLOG`) is held in memory and read with the `SLOWLOG GET` command — it is not written to the log file, so file tailing does not collect it. ## Troubleshooting * **No logs?** If `logfile` is empty, Redis logs to stdout (or journald under systemd). Set a file path in `redis.conf` and restart, or collect from journald with the `journald` receiver. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit If you already run Fluent Bit, tail the Redis log file and forward it over HTTP: ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/redis/redis-server.log tag redis [OUTPUT] name http match redis host ingestion..bronto.io port 443 tls on format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset redis header x-bronto-collection ``` Set **Format** to `json_lines`, not `json`. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit) for installation and the full output reference. # Slack Source: https://docs.bronto.io/integrations/slack Receive Bronto monitor alerts directly in your Slack workspace using incoming webhooks so your team can triage incidents without leaving their chat. ## Overview The Bronto Slack integration lets you route alert notifications to specific Slack channels. Once connected, you can configure multiple integrations — each pointing to a different channel — so the right team gets notified in the right place. ## Setup ### 1. Install the Bronto Slack App 1. Go to **Settings → Integrations** and select **Slack**. 2. Click **Install Slack Application** in the top-right corner. 3. You'll be redirected to Slack to review permissions — Bronto requires access to view channel info and post messages. 4. Select your workspace and click **Allow**. Your workspace will now appear under **Slack Workspaces** on the integration page. ### 2. Invite @bronto.io to Your Channels You must invite `@bronto.io` to each Slack channel where you want alerts to be sent. Bronto cannot post to channels it hasn't been invited to. In Slack, open the target channel and run: ``` /invite @bronto.io ``` Repeat this for every channel you want to receive alerts. ### 3. Create a Slack Integration 1. In Bronto navigate to Settings, Integrations, Slack Integrations, click **+ New**. 2. Fill in the details on the right panel: * **Name** — a label for this integration (e.g. `on-call-alerts`) * **Workspace** — select the connected workspace * **Channels** — enter the target channel (e.g. `#on-call-alerts`) 3. Click **Save**. The integration will now appear in the Slack Integrations table. ## Connecting Integrations to Monitors Once a Slack integration is saved, you can select it as a notification destination when creating or editing a [Monitor](/core-features/monitors). ## Managing Integrations You can create multiple Slack integrations to route different alerts to different channels. Each integration is listed in the **Slack Integrations** table with its name and associated channel(s). To edit or delete an integration, click on its row in the table. # Supabase logs, metrics, and traces Source: https://docs.bronto.io/integrations/supabase Send Supabase Postgres, Auth, Storage, Realtime, and Edge Function logs to Bronto with a log drain and scrape the Metrics API with the OTel Collector. Supabase exposes each signal differently: logs are **pushed** by a log drain, metrics are **pulled** from a Prometheus endpoint, and traces come from your own application, with Supabase propagating the trace context so its logs join your spans. | Signal | How it reaches Bronto | Supabase plan | | - | - | - | | Logs | Log drain posts OTLP directly to Bronto — no infrastructure | Pro, Team, or Enterprise | | Metrics | OpenTelemetry Collector scrapes the Metrics API and forwards OTLP | All plans, including Free | | Traces | Your application exports spans; Supabase propagates `trace_id` into its logs | All plans | ## Prerequisites * A Bronto API key with at least the **Ingestion** role ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * Your Supabase project reference — the 20-character string in **Project Settings → General**, or the subdomain of your project URL * For metrics: a Supabase [secret API key](https://supabase.com/docs/guides/api/api-keys) (`sb_secret_...`) from **Project Settings → API Keys**, and an [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) *** ## Send logs with a log drain A [log drain](https://supabase.com/docs/guides/platform/log-drains) posts logs straight to Bronto's OTLP endpoint. Nothing runs on your side. In the Supabase dashboard, go to **Project Settings → Log Drains** and select **Add drain**. Select **OpenTelemetry (OTLP)** as the destination type. Fill in the fields below, then save the drain. | Field | Value | | - | - | | Endpoint | `https://ingestion..bronto.io/v1/logs` | | Protocol | `http/protobuf` | | Gzip | Enabled | | Header | `x-bronto-api-key` = `` | Replace `` with `eu` or `us`. The drain covers Postgres, Auth, Storage, Realtime, PostgREST, API Gateway, and Edge Function logs. Supabase batches events and delivers on whichever comes first: 250 events or one second. *** ## Send metrics with the OpenTelemetry Collector Every Supabase project serves roughly 200 Postgres performance and health series in [Prometheus format](https://supabase.com/docs/guides/telemetry/metrics) at: ``` https://.supabase.co/customer/v1/privileged/metrics ``` ```yaml /etc/otel/config.yaml theme={"dark"} receivers: prometheus: config: scrape_configs: - job_name: supabase scrape_interval: 60s scrape_timeout: 30s metrics_path: /customer/v1/privileged/metrics scheme: https basic_auth: username: service_role password: static_configs: - targets: [".supabase.co:443"] processors: batch: resource/supabase: attributes: - key: supabase.project_ref value: action: upsert exporters: otlphttp/brontometrics: metrics_endpoint: https://ingestion..bronto.io/v1/metrics compression: gzip headers: x-bronto-api-key: service: pipelines: metrics: receivers: [prometheus] processors: [resource/supabase, batch] exporters: [otlphttp/brontometrics] ``` If your Collector already sends logs or traces, add this receiver and exporter to its `metrics` pipeline and leave the other pipelines alone. See [Send metrics to Bronto](/metrics/send-metrics). The secret API key grants broad access to your project. Treat it as a credential: store it in a secret manager, pass it by environment variable, and rotate it periodically. *** ## Send traces from your application Supabase's managed services do not emit their own spans, but its SDKs propagate [W3C trace context](https://supabase.com/docs/guides/monitoring-and-debugging/client-side-tracing) on Supabase-bound requests. The resulting `trace_id` appears in API Gateway and Edge Function logs, so your application's spans and Supabase's logs land in the same trace — letting you go from a slow request straight to the Postgres statement behind it. Instrument your application with the OpenTelemetry SDK and point it at Bronto — see [Ingest OpenTelemetry data into Bronto](/opentelemetry/overview). *** ## What you will see in Bronto **Metrics** appear in the Metric Explorer — not in a dataset or collection — with roughly 200 distinct series per project. Use the `supabase.project_ref` resource attribute added by the Collector to filter a specific project: | Area | Examples | | - | - | | Database | `pg_database_size_bytes`, query and index statistics, conflicts, recovery state | | Connections | `connection_stats_connection_count`, `direct_connection_stats_connection_count` | | Pooler | `pgbouncer_pools_client_active_connections`, `pgbouncer_pools_server_idle_connections`, `pgbouncer_pools_client_maxwait_seconds` | | Latency | `db_sql_latency_milliseconds` | | Replication | Realtime replication status and lag | | Host | `node_cpu_seconds_total`, `node_filesystem_size_bytes`, disk IO, memory, network | | Auth | `auth_users_user_count` | **Logs** arrive as separate sources for Postgres, Auth, Storage, Realtime, PostgREST, API Gateway, and Edge Functions — see Supabase's [logging reference](https://supabase.com/docs/guides/telemetry/logs) for the fields each one carries — parsed on arrival so fields are searchable without further configuration. ## Troubleshooting | Symptom | Cause | | - | - | | `401` or `403` scraping the Metrics API | The password is not a secret or `service_role` key. The username must be `service_role`. | | `404` scraping the Metrics API | Wrong ``. Check **Project Settings → General**. | | `401` from Bronto | The API key lacks the **Ingestion** role. | | Log drain reports errors | The endpoint must include the `/v1/logs` path, and the protocol must be `http/protobuf`. | | Metrics arrive with no project tag | The `resource/supabase` processor is missing from the `metrics` pipeline. | | No Log Drains option in the dashboard | [Log drains](https://supabase.com/docs/guides/platform/log-drains) require Pro, Team, or Enterprise. | # Traefik logs and metrics with OpenTelemetry Source: https://docs.bronto.io/integrations/traefik Collect Traefik access logs and Prometheus metrics — routing decisions, backend responses, and latency — with the OpenTelemetry Collector. Collect Traefik access logs — routing decisions, backend responses, and latency — with the OpenTelemetry Collector. The same Collector can also forward traces and metrics from your apps — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * Traefik writing access logs to a file in JSON format (Traefik logs to stdout by default — see below) * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) (recommended) or [Fluent Bit](https://docs.fluentbit.io/manual/installation/getting-started-with-fluent-bit) installed on the same host Enable a JSON access log in `traefik.yaml`: ```yaml traefik.yaml theme={"dark"} accessLog: filePath: /var/log/traefik/access.log format: json ``` ## Configure the Collector Traefik's JSON access log is one object per line — parse it with `json_parser`: ```yaml /etc/otel/config.yaml theme={"dark"} receivers: filelog/traefik: include: - /var/log/traefik/access.log operators: - type: json_parser resource: service.name: traefik service.namespace: processors: batch: exporters: otlphttp/brontologs: logs_endpoint: "https://ingestion..bronto.io/v1/logs" compression: gzip headers: x-bronto-api-key: service: pipelines: logs: receivers: [filelog/traefik] processors: [batch] exporters: [otlphttp/brontologs] ``` Set `` to `eu` or `us`. ## Metrics Enable Traefik's Prometheus metrics endpoint, then scrape it with the Collector: ```yaml theme={"dark"} receivers: prometheus: config: scrape_configs: - job_name: traefik static_configs: - targets: [localhost:8080] ``` Add this receiver to the [Bronto metrics pipeline](/metrics/send-metrics). See the [Collector Contrib Prometheus receiver documentation](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/prometheusreceiver), and confirm the Prometheus entry point and metric options against the Traefik version you deploy. ## What you will see in Bronto Open [Search](https://app.bronto.io/search) and filter by `service.name = traefik`. Each entry carries the client address (`ClientHost`), entrypoint, router and service names, method (`RequestMethod`), path (`RequestPath`), status (`DownstreamStatus`), duration (`Duration`), and backend URL. The JSON fields map directly to searchable attributes. ## Troubleshooting * **No log file?** Traefik logs to stdout unless `accessLog.filePath` is set. Add the `accessLog` block above and set `format: json` for automatic field extraction. * For general issues, see [OTel Collector troubleshooting](https://opentelemetry.io/docs/collector/troubleshooting/). ## Alternative: Fluent Bit If you already run Fluent Bit, tail the Traefik access log and forward it over HTTP: ```ini fluent-bit.conf theme={"dark"} [INPUT] name tail path /var/log/traefik/access.log tag traefik [OUTPUT] name http match traefik host ingestion..bronto.io port 443 tls on format json_lines compress gzip header x-bronto-api-key header x-bronto-dataset traefik header x-bronto-collection ``` Set **Format** to `json_lines`, not `json`. See [Connect Fluent Bit to Bronto](/agent-setup/fluent-bit) for installation. # Vercel logs, traces, and analytics Source: https://docs.bronto.io/integrations/vercel Install the Bronto connector from the Vercel Marketplace to stream logs, traces, Speed Insights, and Web Analytics from every Vercel project to Bronto. ## Overview Vercel's [drains](https://vercel.com/docs/drains/using-drains) forward observability data to an external destination in real time. The [Bronto connector on the Vercel Marketplace](https://vercel.com/marketplace/bronto) sets these drains up for you: connect your account once, and Bronto creates the ingestion API key and a drain for each data type in every project in your Vercel team. There are no endpoints or keys to copy. Routing this data into Bronto lets you correlate frontend performance, user behaviour, and backend telemetry in a single place, with long-term retention and unified alerting across your full stack. | Drain | What it contains | Schema reference | | - | - | - | | Logs | Runtime, build, edge, and static logs from your Vercel deployments | [Log Drains reference](https://vercel.com/docs/drains/reference/logs) | | Traces | Distributed OpenTelemetry trace spans across your functions | [Traces reference](https://vercel.com/docs/drains/reference/traces) | | Speed Insights | Core Web Vitals and real user performance metrics | [Speed Insights reference](https://vercel.com/docs/drains/reference/speed-insights) | | Web Analytics | Visitor events and page view data | [Analytics reference](https://vercel.com/docs/drains/reference/analytics) | ## Prerequisites * A **Vercel Pro or Enterprise** plan. See [Vercel's drain documentation](https://vercel.com/docs/drains/using-drains) for plan details. * A Bronto account. You can also create one during the connect flow. The connector creates its own ingestion API key, so you don't need to make one first. *** ## Connect your account Go to [vercel.com/marketplace/bronto](https://vercel.com/marketplace/bronto) and select **Connect Account**. You can also reach the listing from inside Vercel at **Team Settings → Drains → Add Drain → External Integrations**, or from Bronto at **Ingestion → Cloud platforms → Vercel**. Select the Vercel team whose projects you want to stream into Bronto, then approve the access Bronto requests. Bronto uses it to list your projects and create drains on your behalf. Vercel redirects you to the Bronto sign-in page. Sign in to the organisation you want the data to land in, or create an account if you don't have one yet. Bronto links the two accounts. When you see **Vercel Account Linked Successfully!**, select **Back to Vercel**. Drain creation continues in the background. The Bronto organisation you sign in to is the one the drains are created against, and its region decides which ingestion endpoint they use. If you manage more than one Bronto organisation, make sure you're signed in to the right one before you connect. *** ## What the connector creates Once the accounts are linked, Bronto: * Creates a Bronto API key named **Vercel Drain Ingestion API Key** with the **Ingestion** role. Every drain it creates authenticates with this key, and you can see it under [API Keys](/Account-Management/API-Keys). * Lists every project in the connected Vercel team. * Creates four drains per project — Logs, Traces, Speed Insights, and Web Analytics — already pointed at the ingestion endpoint for your Bronto account's region, with the correct encoding and headers. Each drain is named `Bronto Drain - -`, so they're easy to find and edit under **Team Settings → Drains** in Vercel: | Vercel drain name | Data | Encoding | Where it lands in Bronto | | - | - | - | - | | `Bronto Drain - -log` | Logs | NDJSON | Dataset `log`, collection `` | | `Bronto Drain - -speed_insights` | Speed Insights | NDJSON | Dataset `speed_insights`, collection `` | | `Bronto Drain - -analytics` | Web Analytics | NDJSON | Dataset `analytics`, collection `` | | `Bronto Drain - -trace` | Traces | Protobuf (OTLP/HTTP) | [Explore Traces](/tracing/explore-traces) — no dataset or collection | For the log and event drains, the **dataset** tells you which signal the data is and the **collection** tells you which Vercel project it came from. To look at one project in isolation, filter on its collection; to compare projects, query the `log` dataset and group by collection. Traces don't use datasets or collections — find them in Explore Traces and filter by `vercel.projectId`. Drains are created in the background and retried to stay within Vercel's API rate limits, so on a team with many projects it can take a few minutes for all of them to appear under **Team Settings → Drains**. ## After connecting Everything the connector creates is an ordinary Vercel drain that you own from that point on: * **Sampling, sources, and environments** — the connector doesn't add sampling rules, so each drain forwards 100% of the data it covers. Edit a drain in Vercel to narrow its log sources or environments, or to add sampling rules. * **Projects added later** — the connector provisions drains for the projects that exist when you connect. For a project created afterwards, [contact support](mailto:support@bronto.io) to re-run provisioning. * **Audit logs** — audit log drains apply to the whole team rather than to individual projects, so the connector doesn't create one. *** ## Verify Data Flow Once the drains appear under **Team Settings → Drains**, data from your projects begins flowing into Bronto. For Logs, Speed Insights, and Web Analytics, open the `log`, `speed_insights`, or `analytics` dataset in Log Search and filter on the project's collection. For Traces, open [Explore Traces](/tracing/explore-traces) and filter by `vercel.projectId` or `vercel.deploymentId`. *** ## Correlate telemetry across drains With every drain flowing into Bronto, you can look at frontend and backend data side by side instead of switching between tools. The payloads share a few identifiers that make that work: | Field | Present on | Use it to | | - | - | - | | `projectId` / `vercel.projectId` | Logs, Traces, Speed Insights, Web Analytics | Scope every signal to one Vercel project | | `deploymentId` / `vercel.deploymentId` | Logs, Traces, Speed Insights, Web Analytics | Compare a deployment before and after a release | | `traceId` / `spanId` | Logs, Traces | Jump from a log line to its distributed trace and back | | `route` | Speed Insights, Web Analytics | Line up a slow Web Vital with the pages and traffic behind it | For example, when a **Speed Insights** regression shows up on a route, filter **Logs** and **Traces** by the same `deploymentId` to find the release that introduced it, then use the `traceId` on an error log to open the exact span behind it. *** ## Dashboard, monitor, and saved search templates Bronto includes ready-made Vercel templates for dashboards, monitors, and saved searches, built on the data the connector sends. Use them as they are, or as a starting point for your own. There are three Vercel dashboard templates: Overview (Logs), Web Vitals (Speed Insights), and Web Analytics. **Traces** appear in Explore Traces and [correlate](#correlate-telemetry-across-drains) with the other drains, but don't have a dashboard template yet. *** ### Dashboards #### Vercel Overview (Logs drain) A high-level view of request traffic, error rates, cache behaviour, and firewall activity across your Vercel deployments. | Widget | Type | What it shows | | - | - | - | | Total Requests | Query Value | Count of all proxied requests | | 5xx Error Count | Query Value | Count of server error responses | | Lambda Crashes | Query Value | Fatal-level events and status code –1 | | Requests Over Time | Line | Proxied request volume over time | | Requests by Source | Bar | Breakdown by source (build / edge / lambda / static / …) | | HTTP Status Breakdown | Bar | Request count grouped by HTTP status code | | Requests by Method | Bar | Request count grouped by HTTP method | | Cache State Distribution | Bar | Breakdown by `proxy.vercelCache` (HIT / MISS / STALE / …) | | Top Error Paths | Top List | Paths with the most 5xx responses | | Top Edge Regions | Top List | Most active `executionRegion` values | | Firewall Actions | Bar | Request count grouped by WAF action | | Top Denied Clients | Top List | Client IPs most frequently denied by the firewall | | Build Failures Over Time | Line | Build-source error log volume over time | *** #### Vercel Web Vitals (Speed Insights drain) Core Web Vitals at P75, segmented by route and device type, using Google's published "good" thresholds. | Widget | Type | What it shows | | - | - | - | | LCP P75 | Query Value | Largest Contentful Paint at the 75th percentile | | INP P75 | Query Value | Interaction to Next Paint at the 75th percentile | | CLS P75 | Query Value | Cumulative Layout Shift at the 75th percentile | | TTFB P75 | Query Value | Time to First Byte at the 75th percentile | | Web Vitals Over Time (P75) | Line | P75 trend for all metric types | | LCP P75 by Route | Top List | Slowest routes by LCP P75 | | INP P75 by Route | Top List | Slowest routes by INP P75 | | Device Type Breakdown | Bar | Measurement count by device type | *** #### Vercel Web Analytics (Web Analytics drain) Visitor and engagement data from your Vercel Web Analytics drain. | Widget | Type | What it shows | | - | - | - | | Pageviews Over Time | Line | Pageview event volume over time | | Top Pages | Top List | Most visited paths | | Top Custom Events | Top List | Most frequent custom event names | | Referrer Breakdown | Bar | Pageviews grouped by referrer | | Country Distribution | Tree Map | Pageviews grouped by country | | Device Type | Bar | Pageviews grouped by device type | *** ### Monitors Monitors run continuously against your incoming data and fire alerts when thresholds are crossed. All windows are 5 minutes. | Monitor | Drain | Severity | Threshold | | - | - | - | - | | Lambda Error Spike | Logs | Critical | 10 events | | Lambda Crash | Logs | Critical | Any event with status code –1 | | 5xx Error Rate Spike | Logs | Critical | 5% of total requests | | High 4xx Rate | Logs | Warning | 15% of total requests | | Firewall Deny Spike | Logs | Warning | 100 deny events | | LCP P75 Regression | Speed Insights | Warning | P75 > 2,500 ms | | INP P75 Regression | Speed Insights | Warning | P75 > 200 ms | Thresholds for LCP and INP match Google's and Vercel's published "needs improvement" cut-off. You can adjust these in the monitor settings to match your own performance baseline. *** ### Saved Searches Pre-built filters you can open directly from the search bar or use as a starting point for your own investigations. | Name | Drain | What it finds | | - | - | - | | Lambda Errors | Logs | Error and fatal log events from lambda sources | | Lambda Crashes | Logs | Events with status code –1 (process crash) | | Firewall Denies | Logs | Requests denied by the Vercel WAF | | Build Failures | Logs | Error-level events from the build source | | Poor LCP Pages | Speed Insights | LCP measurements above 2,500 ms | | Poor INP Pages | Speed Insights | INP measurements above 200 ms | # Webhooks Source: https://docs.bronto.io/integrations/webhooks Send Bronto monitor alerts to any HTTP endpoint with custom payloads to trigger downstream automation, ticketing, or chat tools when an alert fires. # Webhooks Send custom alert notifications to any HTTP endpoint when a monitor triggers. Webhooks let you integrate Bronto alerts with your own services, on-call tooling, or third-party platforms. ## Overview With Webhooks you can: * Notify your own services when an alert is triggered * Send structured JSON payloads with alert context * Add custom headers for authentication or routing ## Setup ### 1. Create a Webhook 1. Go to **Settings → Integrations** and select **Webhooks**. 2. Click **+ New**. 3. Fill in the details on the right panel: * **Name** — a label for this webhook (e.g. `DevOps Team`) * **URL** — the endpoint Bronto will POST to when an alert fires 4. Click **Save**. The webhook will appear in the Webhooks table with its name and URL. ### 2. Configure the Payload The payload is fully customisable JSON. The following variables are available and will be populated at alert time: | Variable | Description | Example | | - | - | - | | `$alert_id` | Unique identifier of the alert | `10f840e4-9415-481b-ba23-04f6c02bbba0` | | `$current_value` | Value evaluated when the monitor alerted | `10.0` | | `$description` | Description of the monitor | `Monitors authentication logs for dodgy login attempts` | | `$end_time_window` | End of the monitor evaluation window that triggered the alert, as an epoch in milliseconds | `1770284387475` | | `$group` | Monitored group which triggered the alert | `admin` | | `$groups` | Monitored groups which triggered the alert | `admin` | | `$monitor_id` | Unique identifier of the monitor | `f9c2e977-51b7-4947-8a54-7eb47ad99bc4` | | `$monitor_link` | URL to view the monitor in Bronto | `https://app.eu.bronto.io/monitors/...` | | `$monitor_name` | Name of the monitor | `Dodgy Login Monitor` | | `$monitor_type` | Type of the monitor (pattern or change detection) | `pattern` | | `$previous_status` | Previous status of the monitor | `ok` | | `$query` | Query being evaluated by the monitor | `SELECT COUNT(*) WHERE 'dodgy_login'` | | `$region` | Bronto account region name | `eu-west-1` | | `$start_time_window` | Start of the monitor evaluation window that triggered the alert, as an epoch in milliseconds | `1770284327475` | | `$status` | Current status of the monitor | `alert` | | `$summary` | Brief textual summary of the alert | `The query 'SELECT COUNT(*)' is above the defined threshold.` | | `$threshold` | Monitor alert threshold | `5.0` | | `$time_window` | Evaluated time range (human readable) | `2018-05-25T20:23:54.208Z - 2018-05-25T20:28:54.208Z` | | `$time_window_length` | Evaluated time range length in milliseconds | `36,000,000` | | `$title` | Title of the alert | `Monitor has no data: Dodgy Login Monitor` | | `$warn_threshold` | Monitor warning threshold | `3.0` | Some variables may be null or empty if not configured on the monitor. For example, `$warn_threshold` will be empty if no warning threshold has been set. Make sure your service handles missing values gracefully. ### Sample Payload Schema The exact payload sent by Bronto depends on the JSON template you configure, but a typical monitor webhook payload can look like this: ```json theme={"dark"} { "summary": "The query 'SELECT percentile(duration_ms, 95)' is above the defined threshold.", "monitor_link": "https://app.eu.bronto.io/org/11111111-2222-3333-4444-555555555555/monitors/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/view?fromTs=1775653200000&toTs=1775655600000", "monitor_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "query": "SELECT percentile(duration_ms, 95) WHERE 'service.name = checkout'", "groups": {}, "description": "Checkout p95 latency too high", "threshold": "500", "start_time_window": 1775655300000, "title": "Monitor triggered: Checkout p95 Latency", "monitor_name": "Checkout p95 Latency", "current_value": "812", "end_time_window": "1775655300000", "warn_threshold": "", "time_window_length": "Last 5 minutes", "time_window": "2026-04-08T13:35:00Z - 2026-04-08T13:40:00Z", "alert_id": "ffffffff-1111-2222-3333-444444444444", "region": "eu-west-1", "previous_status": "ok", "monitor_type": "pattern", "status": "alert", "group": "" } ``` This example uses redacted UUIDs. Fields such as `group`, `groups`, and `warn_threshold` may be empty depending on the monitor configuration and alert state. ### Change Detection Variables The following additional variables are available only for [Change Detection monitors](/core-features/change-detection): | Variable | Description | Example | | - | - | - | | `$change_type` | Absolute or percentage difference | `difference change (a - b)` | | `$compare_to` | Evaluated comparison time range (human readable) | `2018-05-25T20:23:54.208Z - 2018-05-25T20:28:54.208Z` | | `$compare_to_end_time` | End of the evaluated comparison time range that triggered the alert, as an epoch in milliseconds | `1770284387475` | | `$compare_to_start_time` | Start of the evaluated comparison time range that triggered the alert, as an epoch in milliseconds | `1770284387475` | | `$compare_to_window_value` | Value evaluated from the comparison window when the monitor alerted | `8.0` | | `$current_window_value` | Value evaluated from the current window when the monitor alerted | `10.0` | ### Conditional Statements Conditional statements can be used to determine the content and structure of the payload. For example, the following payload can change based on the monitor status: ```json theme={"dark"} { {{$is_status_alert}}"priority": "HIGH",{{/is_status_alert}} {{!is_status_alert}}"priority": "LOW",{{/is_status_alert}} "action": "dodgy_login" } ``` Bronto will not validate any portion of JSON containing conditional statements, so you must ensure your output is always valid JSON. Any condition can be negated by replacing the `$` with a `!`. | Condition | Description | Example | | - | - | - | | `$is_equal` | Compare two string values; alerting variables are supported | `{{$is_equal '$region' 'eu-west-1'}}{{/is_equal}}` | | `$is_empty` | Check if a variable is not set or has an empty value | `{{$is_empty '$environment'}}{{/is_empty}}` | | `$is_group` | Compare the alerting group name | `{{$is_group 'admins'}}{{/is_group}}` | | `$is_status_alert` | Is the monitor in status "alert"? | `{{$is_status_alert}}{{/is_status_alert}}` | | `$is_status_no_data` | Is the monitor in status "no data"? | `{{$is_status_no_data}}{{/is_status_no_data}}` | | `$is_status_ok` | Is the monitor in status "ok"? | `{{$is_status_ok}}{{/is_status_ok}}` | | `$is_status_warn` | Is the monitor in status "warn"? | `{{$is_status_warn}}{{/is_status_warn}}` | ### 3. Add Custom Headers (Optional) If your endpoint requires authentication or specific headers, click **Add Header** and provide a **Header Name** and **Header Value**. Use the toggle next to a header to encrypt its value. Encrypted header values are stored securely and will not be displayed after saving. When editing an existing webhook, you can leave an encrypted header's value blank to keep the existing secret — it will not be overwritten. ## Connecting Webhooks to Monitors Once saved, a webhook can be selected as a notification destination when creating or editing a [Monitor](/core-features/monitors). ## Managing Webhooks All configured webhooks are listed in the Webhooks table. Click any row to edit or delete it. # Introduction Source: https://docs.bronto.io/introduction Bronto docs cover everything from sending your first events to building dashboards, writing queries, and connecting Bronto to AI tools like MCP. ## Core Workflows Send event data from your hosts and services into Bronto. Search log events across datasets and collections. Use Explore Traces for trace data. Build dashboards and visual views for your data. Manage datasets, parser coverage, data quality, and usage in one place. ## AI Features Bronto includes AI-native features for parsing, investigation, and agent access. Use LLM-powered parsing to convert custom log formats into structured events. Connect supported MCP clients directly to Bronto's hosted MCP endpoint. Run Bronto's open-source MCP server locally and connect AI agents to live log data. Automatically investigate error events and review the evidence behind each finding. ## Need Help? If you need help with Bronto, our team is here to support you. Get help with product questions, troubleshooting, or documentation. Schedule a walkthrough with our team to see Bronto in action. This documentation is continuously updated as Bronto adds new capabilities and improves existing workflows. # Explore Metrics Source: https://docs.bronto.io/metrics/explore-metrics Query Bronto metrics with formulas, inspect histograms, normalize series, configure units, export raw data, and create metric monitors. ## Overview Bronto Metrics lets you query OpenTelemetry metric data, build formulas across metrics, visualize distributions with histograms, overlay multiple metrics on one chart, and alert on thresholds with metric monitors. For metric ingestion setup, see [Send Metrics to Bronto](/metrics/send-metrics). Metrics appear in the Metric Explorer, not in log datasets or collections. Filter metric sources with their OpenTelemetry resource attributes, such as `service.name`. ## Query metrics ### Aggregation functions Aggregation functions combine the data points in each time bucket into a single value. | Function | Description | | - | - | | **Sum** | Sum of all values in the bucket. | | **Average** | Arithmetic mean of the values in the bucket. | | **Min** | Smallest value in the bucket. | | **Max** | Largest value in the bucket. | | **Count** | Number of data points in the bucket. For Histogram and Summary metrics, the sum of their observation counts. | | **Median**, **P25**, **P75**, **P90**, **P95**, **P99**, **P999** | Percentiles from the 25th through the 99.9th percentile. | | **Histogram** | Distribution of values across the bucket. Available for Histogram metrics only. | | **Rate of sum**, **Rate of count** | Per-second rates calculated from the sum or count in the bucket. | The available functions depend on the metric type. The **Histogram** function is not available in monitors. #### Rate For Sum, Summary, and Histogram metrics, select **Rate of sum** or **Rate of count** to convert the selected bucket value into a per-second rate: ```text theme={"dark"} rate = bucket_value / bucket_length_seconds ``` * **Rate of sum** returns the sum of metric values per second. For example, use it to display bytes received per second or tokens used per second. * **Rate of count** returns the number of observations or metric points per second. For Histogram and Summary metrics, this is the rate of recorded observations. For Sum metrics, it is the rate of metric points ingested. | Metric | Type | Rate of sum | Rate of count | | - | - | - | - | | `rpc.server.request.size` | Histogram | Bytes received per second | Requests per second | | `claude_code.token.usage` | Sum | Tokens used per second | Metric points ingested per second | Rate functions are not available for Gauge metrics. They cannot be calculated over **Average**, **Min**, **Max**, or percentile aggregations because the resulting rates would not be meaningful. ### Formulas Formulas combine metrics using arithmetic operators: `+`, `-`, `*`, `/`, and parentheses for grouping. Reference metrics by name and combine them with other metrics or numeric constants. For example, calculate CPU usage as a percentage: ```text theme={"dark"} (container.cpu.usage / container.cpu.limit) * 100 ``` Formulas currently support arithmetic operators only. Function syntax, such as `clamp()`, is not supported. A formula evaluated over a time window with no underlying data currently returns `0` rather than "no value." In a metric monitor, this means a quiet or idle service reads as below threshold instead of no data at every evaluation interval. Account for this behavior when setting formula-based monitor thresholds. ### Histograms Histogram metrics are visualized in the Metrics Explorer as a bar chart, showing the distribution of values across buckets for the selected time range. ### Multi-metric overlay You can overlay multiple metrics on a single chart to compare trends directly instead of switching between separate charts. ### Normalize series For charts with at least three metric queries, use the **Normalize** toggle to compare trends between series with different magnitudes. When normalization is enabled, Bronto scales each series in the selected time range from its own minimum and maximum values into a `0`-to-`1` range. This makes it easier to compare shape and movement across series, such as CPU utilization and request count, without one larger-magnitude series flattening the others visually. When comparing two metric queries, Bronto uses a dual-axis chart automatically if each series has a different unit selected. Units do not affect normalization results, but they do format the values displayed in tooltips. ## Configure units Charts can display metric values in the unit that makes sense for the data. Use the **Unit** menu above the chart to choose how Bronto formats values in the visualization. Available unit types: | Unit type | Use when | | - | - | | None | The metric is already in the right display format, or the value is a plain count. | | Data Volume | The metric represents bytes or another storage/transfer volume, such as memory usage, response size, or network throughput. | | Duration | The metric represents elapsed time, such as request latency, job runtime, or queue wait time. | | Percentage | The metric is a ratio or percentage, such as CPU utilization, error rate, saturation, or cache hit rate. | Unit formatting changes how values appear in the chart. It does not change the underlying metric values. ## Export raw data You can export the underlying raw data behind a metric chart. Exported data contains raw values only. If a chart is configured to display a formatted unit, such as a ratio shown as a percentage, the export does not include a corresponding unit column. The raw, unformatted value is exported. For grouped results, exports may include approximate values in the same cases as search results. For example, when a query returns more than 1000 groups, Bronto may use approximate group results. If an exported CSV contains approximate results, the relevant column headers include an `[approximate]` tag. ## Metric monitors Metric monitors alert when a metric or formula crosses a threshold you define. Use them to monitor service and infrastructure signals such as CPU utilization, memory usage, request rate, latency, or error totals. To create one, go to **Monitors** > **New Monitor**, set the query **Data source** to **Metrics**, then search for and select the metric you want to evaluate. Add more metric queries with **+ Add Query**, or use **+ Add Formula** to alert on a calculated value across metrics. When setting a metric monitor threshold, unit selection is a display helper. It lets you enter the threshold in a convenient unit and formats the preview chart, but the monitor is still created and evaluated against the translated raw value. For the general monitor workflow and notification options, see [Monitoring Overview & Threshold Monitors](/core-features/monitors). If formula-based monitors fire unexpectedly on a quiet service, review the no-data behavior under [Formulas](#formulas). If exported CSVs are missing display units, review [Export raw data](#export-raw-data). # Send Metrics to Bronto Source: https://docs.bronto.io/metrics/send-metrics Send OpenTelemetry metrics to Bronto using OTLP over HTTP, exported directly from an OTel SDK or routed through an OpenTelemetry Collector. Bronto accepts OpenTelemetry metrics over OTLP/HTTP. You can export metrics directly from an OpenTelemetry SDK or route them through an OpenTelemetry Collector before forwarding them to Bronto. Bronto recommends enabling logs, metrics, and traces together so every service has a consistent telemetry pipeline. If you only need metrics, OpenTelemetry lets you enable the metrics exporter and pipeline independently. Metrics are not stored in Bronto datasets or collections. Sending metrics does not create a dataset, and the `x-bronto-dataset`, `x-bronto-collection`, and `x-bronto-tags` log-routing headers do not organize metrics. Use OpenTelemetry resource attributes such as `service.name` to identify metric sources, then view the data in the [Metric Explorer](/metrics/explore-metrics). ## Supported metric types | OpenTelemetry metric type | Support | | - | - | | Gauge | Supported | | Sum, including counters | Supported | | Summary | Supported | | Explicit-bucket histogram | Supported | | Exponential histogram | Not currently supported | Bronto supports ingestion of sum and histogram metrics as delta or cumulative. Delta is strongly recommended to get the best value from the current set of supported functions. After ingestion, you can calculate per-second rates for Sum, Summary, and Histogram metrics in Metrics, Dashboards, and metric monitors. See [Aggregation functions](/metrics/explore-metrics#aggregation-functions). ## Prerequisites Before you begin, you need: * a Bronto API key with ingestion permissions * your Bronto region: `eu` or `us` * an application instrumented with an OpenTelemetry metrics SDK, or an OpenTelemetry Collector receiving metrics ## Endpoint and authentication Use the metrics endpoint for your Bronto region: | Region | Metrics endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io/v1/metrics` | | US | `https://ingestion.us.bronto.io/v1/metrics` | Both endpoints accept OTLP/HTTP over HTTPS on port `443`, in either protobuf (`Content-Type: application/x-protobuf`) or JSON (`Content-Type: application/json`) encoding. Every request must include: ```text theme={"dark"} x-bronto-api-key: ``` ## Send metrics through an OpenTelemetry Collector Configure an OTLP receiver and an OTLP/HTTP exporter that targets the Bronto metrics endpoint: The example uses the standard Collector receiver ports: `4317` for OTLP/gRPC and `4318` for OTLP/HTTP. A same-host application typically exports OTLP/HTTP metrics to `http://localhost:4318/v1/metrics`; replace the host, port, protocol, and TLS settings when your deployment differs. ```yaml otel-config.yaml theme={"dark"} receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: cumulativetodelta: initial_value: drop exporters: otlphttp/brontometrics: metrics_endpoint: https://ingestion..bronto.io/v1/metrics compression: gzip headers: x-bronto-api-key: service: pipelines: metrics: receivers: [otlp] processors: [cumulativetodelta, batch] exporters: [otlphttp/brontometrics] ``` Replace `` with `eu` or `us`. If your Collector also sends logs and traces, add the Bronto metrics exporter to its `metrics` pipeline and keep the existing signal pipelines. Each signal uses its own endpoint. ## Send metrics directly from an SDK For SDKs that support OTLP/HTTP configuration through environment variables: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT="https://ingestion..bronto.io/v1/metrics" export OTEL_EXPORTER_OTLP_METRICS_HEADERS="x-bronto-api-key=" export OTEL_METRICS_EXPORTER="otlp" export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf" ``` Configure a meter provider and periodic metric reader in your application. Use the [language-specific OpenTelemetry guides](/opentelemetry/overview) for SDK setup. ## Resource attributes Set resource attributes once and share them across logs, metrics, and traces: ```bash theme={"dark"} export OTEL_RESOURCE_ATTRIBUTES="service.name=checkout,service.namespace=production,deployment.environment.name=production" ``` At minimum, set `service.name` so metrics can be associated with the service that emitted them. For metrics, this is a filterable resource attribute; it is not a dataset name and does not create a dataset. ## Verify metric delivery 1. Open **Metric Explorer** in Bronto. 2. Select a recently emitted metric. 3. Confirm its service and resource attributes are present. 4. Compare the latest timestamp with the export interval configured in your SDK or Collector. ## Troubleshooting If metrics do not appear: * confirm the endpoint matches your Bronto region and ends in `/v1/metrics` * confirm the `x-bronto-api-key` header is present * confirm the Collector has an enabled `metrics` pipeline * check that the SDK has a metric reader and exporter configured * check Collector logs for rejected exponential histograms * allow at least one SDK export interval before checking Metric Explorer For a combined logs, metrics, and traces setup, see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). ## Further reading * [OpenTelemetry metrics concepts](https://opentelemetry.io/docs/concepts/signals/metrics/) * [OpenTelemetry OTLP exporter configuration](https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/) * [Explore Metrics](/metrics/explore-metrics) — query, visualize, export, and monitor metrics after ingestion # Send C++ logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/cpp Instrument C++ applications with the OpenTelemetry C++ SDK to send logs, metrics, and traces to Bronto over OTLP/HTTP, via an OTel Collector or directly. One initialisation function sends **logs, metrics, and traces** from your C++ application to Bronto. All three providers share a single `Resource`, so telemetry from the process carries one identity. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — only the URL and an API key header change. C++ has no automatic bridge from a popular logging library (spdlog, glog) in the official SDK, and auto-instrumentation coverage is thinner than in other languages. Log records are emitted through the OTel logs API directly, as shown below. Check the [OpenTelemetry C++ registry](https://opentelemetry.io/ecosystem/registry/?language=cpp) for community bridges and instrumentation. ## Prerequisites * C++14 or later, CMake 3.12 or later * vcpkg or Conan, or a manual build of `opentelemetry-cpp` * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Install dependencies ```bash vcpkg theme={"dark"} vcpkg install opentelemetry-cpp ``` ```bash Conan theme={"dark"} conan install opentelemetry-cpp/1.17.0@ --build=missing ``` Link the components for all three signals in your `CMakeLists.txt`: ```cmake CMakeLists.txt theme={"dark"} find_package(opentelemetry-cpp CONFIG REQUIRED) target_link_libraries(myapp PRIVATE opentelemetry-cpp::logs opentelemetry-cpp::metrics opentelemetry-cpp::trace opentelemetry-cpp::otlp_http_log_record_exporter opentelemetry-cpp::otlp_http_metric_exporter opentelemetry-cpp::otlp_http_exporter opentelemetry-cpp::resources ) ``` ## Initialise the SDK Call `InitOtel()` once at startup, before any span or log emission: ```cpp otel.cpp theme={"dark"} #include "opentelemetry/exporters/otlp/otlp_http_exporter_factory.h" #include "opentelemetry/exporters/otlp/otlp_http_exporter_options.h" #include "opentelemetry/exporters/otlp/otlp_http_log_record_exporter_factory.h" #include "opentelemetry/exporters/otlp/otlp_http_log_record_exporter_options.h" #include "opentelemetry/exporters/otlp/otlp_http_metric_exporter_factory.h" #include "opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h" #include "opentelemetry/logs/provider.h" #include "opentelemetry/metrics/provider.h" #include "opentelemetry/sdk/logs/logger_provider_factory.h" #include "opentelemetry/sdk/logs/processor/batch_log_record_processor_factory.h" #include "opentelemetry/sdk/metrics/meter_provider.h" #include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h" #include "opentelemetry/sdk/resource/resource.h" #include "opentelemetry/sdk/trace/batch_span_processor_factory.h" #include "opentelemetry/sdk/trace/tracer_provider_factory.h" #include "opentelemetry/trace/provider.h" namespace logs_api = opentelemetry::logs; namespace logs_sdk = opentelemetry::sdk::logs; namespace metrics_api = opentelemetry::metrics; namespace metrics_sdk = opentelemetry::sdk::metrics; namespace otlp = opentelemetry::exporter::otlp; namespace resource = opentelemetry::sdk::resource; namespace trace_api = opentelemetry::trace; namespace trace_sdk = opentelemetry::sdk::trace; constexpr const char *kOtlpEndpoint = "http://localhost:4318"; void InitOtel() { auto res = resource::Resource::Create({ {"service.name", "my-service"}, {"service.namespace", "my-team"}, {"deployment.environment", "production"}, }); // Logs otlp::OtlpHttpLogRecordExporterOptions log_opts; log_opts.url = std::string(kOtlpEndpoint) + "/v1/logs"; auto log_provider = logs_sdk::LoggerProviderFactory::Create( logs_sdk::BatchLogRecordProcessorFactory::Create( otlp::OtlpHttpLogRecordExporterFactory::Create(log_opts), {}), res); logs_api::Provider::SetLoggerProvider( opentelemetry::nostd::shared_ptr(log_provider.release())); // Metrics otlp::OtlpHttpMetricExporterOptions metric_opts; metric_opts.url = std::string(kOtlpEndpoint) + "/v1/metrics"; auto reader = metrics_sdk::PeriodicExportingMetricReaderFactory::Create( otlp::OtlpHttpMetricExporterFactory::Create(metric_opts), {}); auto meter_provider = std::shared_ptr( new metrics_sdk::MeterProvider({}, res)); meter_provider->AddMetricReader(std::move(reader)); metrics_api::Provider::SetMeterProvider( opentelemetry::nostd::shared_ptr(meter_provider)); // Traces otlp::OtlpHttpExporterOptions trace_opts; trace_opts.url = std::string(kOtlpEndpoint) + "/v1/traces"; auto tracer_provider = trace_sdk::TracerProviderFactory::Create( trace_sdk::BatchSpanProcessorFactory::Create( otlp::OtlpHttpExporterFactory::Create(trace_opts), {}), res); trace_api::Provider::SetTracerProvider( opentelemetry::nostd::shared_ptr(tracer_provider.release())); } ``` The metrics factory signatures vary across `opentelemetry-cpp` releases more than the logs and traces ones. If the block above doesn't compile against your build, check the metrics example for your version in the [opentelemetry-cpp repository](https://github.com/open-telemetry/opentelemetry-cpp/tree/main/examples). Two resource attributes identify the source across all three signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Metrics and traces are not stored in datasets or collections. View them in the Metric Explorer and Explore Traces, filtering by these resource attributes. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. ## Instrument your application ```cpp main.cpp theme={"dark"} #include "otel.h" int main() { InitOtel(); auto logger = logs_api::Provider::GetLoggerProvider() ->GetLogger("my-logger", "my-service"); auto tracer = trace_api::Provider::GetTracerProvider() ->GetTracer("my-service"); auto payments = metrics_api::Provider::GetMeterProvider() ->GetMeter("my-service") ->CreateUInt64Counter("app.payments"); { auto span = tracer->StartSpan("process-payment"); auto scope = tracer->WithActiveSpan(span); span->SetAttribute("payment.amount", 99.99); payments->Add(1); logger->EmitLogRecord(logs_api::Severity::kInfo, "Processing payment"); span->End(); } // Flush buffered telemetry before exit. logs_api::Provider::GetLoggerProvider()->ForceFlush(); return 0; } ``` A log record emitted inside an active span picks up that span's `trace_id` and `span_id` from the current context, so you can jump from a log line to its trace in Bronto. ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Metrics** — the Metric Explorer * **Traces** — the Explore Traces page If nothing arrives: * Confirm the Collector is running and reachable at the configured URL, and that its pipelines include an `otlp` receiver and the Bronto exporters. * Confirm `InitOtel()` runs before the first log or span. * The batch processors export on a background thread — call `ForceFlush()` before exit so short-lived programs flush. For signal-specific reference material, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). ## Direct export to Bronto Without a Collector, the application exports straight to Bronto over OTLP/HTTP. Point the endpoint at your Bronto region and add your API key to each exporter's options: ```cpp theme={"dark"} constexpr const char *kOtlpEndpoint = "https://ingestion.eu.bronto.io"; // or ingestion.us.bronto.io log_opts.url = std::string(kOtlpEndpoint) + "/v1/logs"; log_opts.http_headers.insert({"x-bronto-api-key", ""}); ``` Apply the same `http_headers` insert to `metric_opts` and `trace_opts`. | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector for multi-service environments — it batches, filters, and enriches telemetry, and keeps the API key out of every application. Direct export suits single services and simple architectures. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. ### Manual spans There is no first-party GenAI instrumentation for C++, so set the attributes yourself around each model call: ```cpp theme={"dark"} auto span = tracer->StartSpan("chat gpt-4o-mini"); auto scope = tracer->WithActiveSpan(span); span->SetAttribute("gen_ai.provider.name", "openai"); span->SetAttribute("gen_ai.request.model", "gpt-4o-mini"); span->SetAttribute("gen_ai.usage.input_tokens", 33); span->SetAttribute("gen_ai.usage.output_tokens", 74); // Bronto flattens array attributes — this is searchable as finish_reasons.0 span->SetAttribute("gen_ai.response.finish_reasons", std::vector{"stop"}); span->End(); ``` Message content (`gen_ai.input.messages` / `gen_ai.output.messages`) is opt-in by convention and off by default in the languages that have auto-instrumentation. Since you are setting attributes by hand, apply the same discipline — gate prompt and response content behind your own config flag rather than always sending it. See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). # Send .NET logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/dotnet Instrument .NET and ASP.NET Core apps with the OpenTelemetry .NET SDK to send logs, metrics, and traces to Bronto over OTLP/HTTP, directly or via a Collector. One `AddOpenTelemetry()` block sends **logs, metrics, and traces** from your .NET application to Bronto. Existing `ILogger` calls feed the log pipeline, instruments feed the meter provider, and activities feed the tracer provider — all three sharing one resource identity and one OTLP exporter. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — only the endpoint and an API key header change. ## Prerequisites * .NET 8 or later * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Install dependencies ```bash theme={"dark"} dotnet add package OpenTelemetry.Extensions.Hosting dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol dotnet add package OpenTelemetry.Instrumentation.AspNetCore dotnet add package OpenTelemetry.Instrumentation.Http ``` The two instrumentation packages produce request and HTTP client spans and metrics automatically. See [.NET instrumentation libraries](https://opentelemetry.io/docs/languages/dotnet/libraries/) for the full list, including Entity Framework Core and gRPC. ## Initialise the SDK Configure all three signals in `Program.cs`: ```csharp Program.cs theme={"dark"} using OpenTelemetry.Exporter; using OpenTelemetry.Logs; using OpenTelemetry.Metrics; using OpenTelemetry.Resources; using OpenTelemetry.Trace; var builder = WebApplication.CreateBuilder(args); // Bridge ILogger into the OTel pipeline. builder.Logging.AddOpenTelemetry(logging => { logging.IncludeFormattedMessage = true; logging.IncludeScopes = true; }); builder.Services.AddOpenTelemetry() .ConfigureResource(resource => resource .AddService(serviceName: "my-service", serviceNamespace: "my-team") .AddAttributes(new Dictionary { ["deployment.environment"] = "production", })) .WithMetrics(metrics => metrics .AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddMeter("my-service")) .WithTracing(tracing => tracing .AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddSource("my-service")) .UseOtlpExporter(OtlpExportProtocol.HttpProtobuf, new Uri("http://localhost:4318/")); var app = builder.Build(); app.Run(); ``` `UseOtlpExporter` enables the exporter for logs, metrics, and traces in one call, appending the signal path (`/v1/logs`, `/v1/metrics`, `/v1/traces`) to the base URL. `ConfigureResource` applies across all three signals, so `service.name` and `service.namespace` are shared automatically. Two resource attributes identify the source across all three signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Metrics and traces are not stored in datasets or collections. View them in the Metric Explorer and Explore Traces, filtering by these resource attributes. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. For console applications and workers, use `Host.CreateApplicationBuilder(args)` in place of `WebApplication.CreateBuilder(args)`. The `AddOpenTelemetry()` block is identical. ## Instrument your application `ILogger` calls need no changes. Add a `Meter` and an `ActivitySource` for your own measurements and spans: ```csharp theme={"dark"} using System.Diagnostics; using System.Diagnostics.Metrics; public class PaymentService { private static readonly ActivitySource ActivitySource = new("my-service"); private static readonly Meter Meter = new("my-service"); private static readonly Counter Payments = Meter.CreateCounter("app.payments"); private readonly ILogger _logger; public PaymentService(ILogger logger) => _logger = logger; public void ProcessPayment(decimal amount) { using var activity = ActivitySource.StartActivity("process-payment"); activity?.SetTag("payment.amount", amount); Payments.Add(1); _logger.LogInformation("Processing payment"); // trace_id and span_id attached automatically } } ``` The `AddSource` and `AddMeter` names in `Program.cs` must match the `ActivitySource` and `Meter` names here, or their telemetry is dropped. Any `ILogger` call made inside an active `Activity` automatically carries that span's `trace_id` and `span_id`, so you can jump from a log line to its trace in Bronto with no manual context propagation. ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Metrics** — the Metric Explorer * **Traces** — the Explore Traces page If nothing arrives: * Confirm the Collector is running and reachable at the configured endpoint, and that its pipelines include an `otlp` receiver and the Bronto exporters. * Confirm `OtlpExportProtocol.HttpProtobuf` matches the Collector receiver you are pointing at — port `4318` is HTTP, `4317` is gRPC. * Check that every `ActivitySource` and `Meter` name is registered with `AddSource` / `AddMeter`. For signal-specific reference material, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). ## Direct export to Bronto Without a Collector, the application exports straight to Bronto over OTLP/HTTP. Point the base URL at your Bronto region: ```csharp Program.cs theme={"dark"} .UseOtlpExporter( OtlpExportProtocol.HttpProtobuf, new Uri("https://ingestion.eu.bronto.io/")); // or ingestion.us.bronto.io ``` and supply your API key through the standard OTLP header variable, which `UseOtlpExporter` reads: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=" ``` | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector for multi-service environments — it batches, filters, and enriches telemetry, and keeps the API key out of every application. Direct export suits single services and simple architectures. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. .NET GenAI telemetry is library-specific — each has its own opt-in, and each emits from its own activity source, which you register with `AddSource`: | Library | Enable with | Activity source | | - | - | - | | Semantic Kernel | `SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS=true` | `Microsoft.SemanticKernel*` | | OpenAI .NET SDK | `AppContext.SetSwitch("OpenAI.Experimental.EnableOpenTelemetry", true)` | `OpenAI.*` | | Microsoft.Extensions.AI | Wrap the `IChatClient` with `UseOpenTelemetry()` | `Experimental.Microsoft.Extensions.AI` | | AWS SDK (Bedrock) | `OpenTelemetry.Instrumentation.AWS` package | added by `AddAWSInstrumentation()` | These APIs are experimental and version-sensitive, so verify the attributes emitted by the version you deploy against each library's current documentation. ### Capture prompts and responses Content capture is controlled by the .NET library rather than the cross-language OTel variables — `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT`, used by the Python, JavaScript, and Java instrumentations, is not a .NET-wide switch. Semantic Kernel uses its own sensitive-diagnostics opt-in: ```bash theme={"dark"} export SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE=true ``` Microsoft.Extensions.AI uses the `EnableSensitiveData` option on `UseOpenTelemetry()` instead. Prompt and response content can contain sensitive data, so enable it deliberately. ### Manual spans Where no instrumentation exists for your provider, set the same attributes yourself: ```csharp theme={"dark"} private static readonly ActivitySource ActivitySource = new("my-service"); using var activity = ActivitySource.StartActivity("chat gpt-4o-mini"); activity?.SetTag("gen_ai.provider.name", "openai"); activity?.SetTag("gen_ai.request.model", "gpt-4o-mini"); activity?.SetTag("gen_ai.usage.input_tokens", 33); activity?.SetTag("gen_ai.usage.output_tokens", 74); // Bronto flattens array attributes — this is searchable as finish_reasons.0 activity?.SetTag("gen_ai.response.finish_reasons", new[] { "stop" }); ``` See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). # Zero-code instrumentation with eBPF Source: https://docs.bronto.io/opentelemetry/ebpf Instrument applications with OpenTelemetry eBPF Instrumentation (OBI) to send traces and RED metrics to Bronto with no code changes and no redeploy. [OpenTelemetry eBPF Instrumentation](https://opentelemetry.io/docs/zero-code/obi/) (OBI) produces distributed traces and RED metrics for services that contain no instrumentation at all — no SDK dependency, no initialisation code, and no redeploy. It attaches eBPF programs to already-running processes and reads HTTP and gRPC activity as it crosses the kernel boundary. This makes it the fastest way to get coverage across an estate, and the only practical option for services whose build you do not control: vendored binaries, legacy applications, and third-party components. OBI is the OpenTelemetry project donated from Grafana Beyla. If you have used Beyla, the configuration keys are the same with an `OTEL_EBPF_` prefix instead of `BEYLA_`. ## When to use eBPF instead of an SDK eBPF observes the process boundary, so it sees requests between services rather than logic inside them. The two approaches complement each other and land in Bronto through the same OTLP pipeline, with matching trace IDs. | | eBPF (OBI) | OpenTelemetry SDK | | - | - | - | | Code changes | None | Dependency plus initialisation | | Redeploy needed | No | Yes | | Coverage | HTTP and gRPC at the process boundary | Anything you instrument | | Custom attributes | No | Yes | | Business-logic spans | No | Yes | | Logs | No — [ship separately](/agent-setup/agent-intro) | Yes, via the log bridge | **Use eBPF** for immediate breadth, for services you cannot rebuild, and to find out where latency and errors actually are. **Add an SDK** in the services that then warrant domain detail. See [Choose your language](/opentelemetry/overview) for SDK setup. ## Requirements | Requirement | Detail | | - | - | | Kernel | Linux 5.8+; **5.17+** for distributed traces across services | | BTF | `/sys/kernel/btf/vmlinux` must be present | | Architecture | amd64 or arm64 | | Privileges | Root, or the [documented capability set](https://opentelemetry.io/docs/zero-code/obi/security/), plus host PID namespace access | Check a host before you start: ```bash theme={"dark"} uname -r && ls -l /sys/kernel/btf/vmlinux ``` This also works on Docker Desktop for macOS, which runs a LinuxKit VM with BTF enabled — useful for evaluating OBI before deploying it to a cluster. ## Prerequisites * A Bronto account and API key ([how to create one](/Account-Management/API-Keys#create-a-new-api-key)) * An [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/installation/) — recommended, and required if you want delta metrics * A host or cluster meeting the requirements above ## Run OBI with Docker Compose OBI runs as one container alongside your services. It needs the host PID namespace to see other containers' processes, and elevated privileges to load eBPF programs. ```yaml docker-compose.yml theme={"dark"} services: obi: image: otel/ebpf-instrument:main pid: "host" privileged: true environment: OTEL_EBPF_CONFIG_PATH: /etc/obi/obi.yml volumes: - ./obi.yml:/etc/obi/obi.yml:ro depends_on: [otel-collector] ``` OBI discovers what to instrument by the ports your services listen on — the applications themselves are not modified or restarted: ```yaml obi.yml theme={"dark"} discovery: instrument: # The ports your services listen on. - open_ports: 8080,3000,5000 containers_only: true exclude_instrument: # Publishing a port makes the Docker daemon listen on it too, so a # port selector matches dockerd unless you exclude it explicitly. - exe_path: "*dockerd*" - exe_path: "*docker-proxy*" - exe_path: "*containerd*" - exe_path: "*otelcol*" ebpf: # Inject W3C trace context into outgoing requests so spans from different # services join into one distributed trace. Requires kernel 5.17+. context_propagation: all otel_traces_export: endpoint: http://otel-collector:4318 otel_metrics_export: endpoint: http://otel-collector:4318 interval: 15s features: - application - application_span ``` ## Run OBI on Kubernetes Deploy OBI as a DaemonSet so every node instruments its own pods. The container needs `hostPID: true` and the eBPF capabilities: ```yaml obi-daemonset.yaml theme={"dark"} apiVersion: apps/v1 kind: DaemonSet metadata: name: obi spec: selector: matchLabels: { app: obi } template: metadata: labels: { app: obi } spec: hostPID: true containers: - name: obi image: otel/ebpf-instrument:main securityContext: privileged: true env: - name: OTEL_EBPF_CONFIG_PATH value: /etc/obi/obi.yml - name: OTEL_EBPF_BPF_CONTEXT_PROPAGATION value: all volumeMounts: - { name: config, mountPath: /etc/obi } volumes: - name: config configMap: { name: obi-config } ``` On Kubernetes you can select workloads by namespace, labels, or annotations instead of ports: ```yaml obi.yml theme={"dark"} discovery: instrument: - k8s_namespace: production k8s_pod_labels: instrument: obi ``` See [Kubernetes logs and metrics with OpenTelemetry](/integrations/kubernetes) for collecting pod logs alongside this. ## Forward to Bronto Point the Collector's OTLP receiver at Bronto's trace and metric endpoints. Traces and metrics use separate endpoints and the same API key header: ```yaml otel-config.yaml theme={"dark"} receivers: otlp: protocols: grpc: { endpoint: 0.0.0.0:4317 } http: { endpoint: 0.0.0.0:4318 } processors: batch: # OBI exports cumulative metrics; Bronto strongly prefers delta. cumulativetodelta: initial_value: drop exporters: otlphttp/brontotraces: traces_endpoint: "https://ingestion..bronto.io/v1/traces" compression: gzip headers: x-bronto-api-key: otlphttp/brontometrics: metrics_endpoint: "https://ingestion..bronto.io/v1/metrics" compression: gzip headers: x-bronto-api-key: service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [otlphttp/brontotraces] metrics: receivers: [otlp] processors: [cumulativetodelta, batch] exporters: [otlphttp/brontometrics] ``` Replace `` with `eu` or `us` to match your account. A mismatched region returns `401`, which looks identical to an invalid key. Do not set `histogram_aggregation: base2_exponential_bucket_histogram`. Bronto does not currently ingest exponential histograms. OBI's default, `explicit_bucket_histogram`, is the correct setting. ## Name your services By default OBI names a service after its executable. That is fine for a compiled binary, but interpreted runtimes all end up named after the interpreter — `node`, `python3.13`, `java`. OBI reads `OTEL_SERVICE_NAME` and `OTEL_RESOURCE_ATTRIBUTES` from each target process's **own environment**, so you can name services without adding an SDK or touching application code: ```yaml docker-compose.yml theme={"dark"} services: checkout-api: image: your-app:latest environment: OTEL_SERVICE_NAME: checkout-api OTEL_RESOURCE_ATTRIBUTES: service.namespace=production ``` Nothing inside the container reads these variables — OBI does, from the outside. Traces and metrics are not stored in Bronto datasets or collections. `service.name` and `service.namespace` are carried on spans and measurements as resource attributes; use them to filter services and environments in Explore Traces and the Metric Explorer. ## What you will see in Bronto OBI emits standard OpenTelemetry semantic conventions, so no Bronto-specific configuration is required. **Traces.** Each request produces a server span, client spans for outgoing calls, and — for Go services — an `in queue` and `processing` breakdown that separates time spent waiting to be handled from time spent being handled: ``` checkout-api SERVER GET /checkout 50.65ms checkout-api INTERNAL in queue 0.20ms checkout-api INTERNAL processing 50.45ms checkout-api CLIENT GET /orders 49.93ms orders-api SERVER GET /orders 48.28ms orders-api CLIENT GET /inventory 46.54ms inventory SERVER GET /inventory 46.35ms ``` **Metrics.** RED metrics per route and status code: ``` http.server.request.duration http.server.request.body.size http.server.response.body.size http.client.request.duration traces_spanmetrics_calls_total traces_spanmetrics_latency ``` **Searchable span fields.** `span.trace_id`, `span.parent_span_id`, `span.kind`, `span.duration_nano`, `http.route`, `http.request.method`, `http.response.status_code`, `service.name`, `service.namespace`, and `url.path`. Spans produced by OBI carry `telemetry.distro.name = opentelemetry-ebpf-instrumentation`, which is a convenient way to separate eBPF-derived data from SDK-derived data in queries. ## Verify OBI logs one line per instrumented process, including the runtime it detected: ``` instrumenting process cmd=/usr/local/bin/checkout-api type=go instrumenting process cmd=/usr/local/bin/node type=nodejs instrumenting process cmd=/usr/local/bin/python3.13 type=python ``` If nothing appears, your selector matched no processes — check `open_ports` against the ports your services actually listen on. Set `trace_printer: text` in `obi.yml` to have OBI print every captured span to stdout as well as exporting it. Send a request through your service and confirm spans appear, then set it back to `disabled`. Look for export errors in the Collector's logs: ```bash theme={"dark"} docker compose logs otel-collector | grep -i "exporting failed" ``` A `401` means the API key or the region is wrong. Open [Explore Traces](/tracing/explore-traces) and filter on your `service.name`, or query `service.namespace` to see the whole environment. Metrics appear in the Metric Explorer under `http.server.request.duration`. ## Troubleshooting * **Spans appear but never join into a trace.** Context propagation is off by default. Set `context_propagation: all` and confirm the kernel is 5.17+. * **A service you did not expect is being instrumented.** Publishing a container port makes the Docker daemon listen on it too. Add `dockerd`, `docker-proxy`, and `containerd` to `exclude_instrument`. * **Go services produce fewer details than expected.** OBI attaches uprobes to Go runtime symbols. Building with `-ldflags="-s -w"` strips the symbol table and silently degrades OBI to generic syscall tracing — leave Go binaries unstripped. * **`creating OTEL namespace in bpffs failed`.** `/sys/fs/bpf` is not mounted. Core tracing still works; features that rely on pinned maps, such as the log enricher, are disabled. Mount bpffs to restore them. * **`FIONREAD compensation is ineffective`.** Applications that size reads via `FIONREAD` — nginx, Java, and .NET among them — may stall or truncate transfers while context propagation is enabled. Validate against those runtimes, or set `context_propagation: disabled` for them. * **Metrics rejected or missing.** Confirm you are not exporting exponential histograms, and that `cumulativetodelta` is in the metrics pipeline. ## Security considerations Running with `privileged: true` is the documented starting point and the simplest way to prove the setup works, but it grants more than OBI needs. For production, use the [least-privilege capability set](https://opentelemetry.io/docs/zero-code/obi/security/) — `CAP_BPF`, `CAP_PERFMON`, `CAP_NET_RAW`, and `CAP_DAC_READ_SEARCH` among others, depending on the features you enable. Set `OTEL_EBPF_ENFORCE_SYS_CAPS=true` so OBI fails loudly when a required capability is missing instead of degrading quietly. Host PID namespace access is not optional: OBI must see other processes in order to attach to them. Go library-level context propagation relies on `bpf_probe_write_user`, which is blocked by Secure Boot and kernel lockdown mode. Network-level propagation still works in those environments. ## Next steps * [Explore Traces](/tracing/explore-traces) — investigate services, latency, and errors * [Send Metrics to Bronto](/metrics/send-metrics) — metric support and limitations * [Choose your language](/opentelemetry/overview) — add SDK instrumentation where you need business context * [Agent Setup](/agent-setup/agent-intro) — ship logs, which OBI does not produce * [Connect Odigos to Bronto](/agent-setup/odigos) — a Kubernetes-native platform that manages eBPF instrumentation and collectors for you * [OBI documentation](https://opentelemetry.io/docs/zero-code/obi/) — full configuration reference # Send Erlang and Elixir logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/erlang-elixir Instrument Erlang or Elixir BEAM apps with the OpenTelemetry SDK to send logs, metrics, and traces to Bronto over OTLP/HTTP, directly or via a Collector. On the BEAM, OpenTelemetry is configured entirely in application config — no initialisation code. One config block sends **logs and traces** to Bronto: the SDK installs a kernel logger handler that captures every `Logger` / `:logger` call, and framework instrumentation libraries produce spans for Phoenix, Ecto, and friends. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — only the endpoint and an API key header change. Metrics on the BEAM live in the separate `opentelemetry_experimental` package and the instrument API is still unstable. Logs and traces, covered below, are stable. See [metrics](#metrics) at the end of this page. ## Prerequisites * Erlang/OTP 24 or later, or Elixir 1.13 or later * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Install dependencies ```elixir Elixir (mix.exs) theme={"dark"} def deps do [ {:opentelemetry_api, "~> 1.4"}, {:opentelemetry, "~> 1.4"}, {:opentelemetry_exporter, "~> 1.7"}, # framework instrumentation — add what applies {:opentelemetry_phoenix, "~> 1.2"}, {:opentelemetry_ecto, "~> 1.2"} ] end ``` ```erlang Erlang (rebar.config) theme={"dark"} {deps, [ {opentelemetry_api, "~> 1.4"}, {opentelemetry, "~> 1.4"}, {opentelemetry_exporter, "~> 1.7"} ]}. ``` See [Erlang/Elixir instrumentation libraries](https://opentelemetry.io/docs/languages/erlang/libraries/) for the full list, including LiveView and Absinthe. ## Configure the SDK ```elixir Elixir (config/config.exs) theme={"dark"} import Config config :opentelemetry, resource: [ service: [name: "my-service", namespace: "my-team"], "deployment.environment": "production" ], traces_exporter: :otlp, logs_exporter: :otlp config :opentelemetry_exporter, otlp_protocol: :http_protobuf, otlp_endpoint: "http://localhost:4318" ``` ```erlang Erlang (sys.config) theme={"dark"} [ {opentelemetry, [ {resource, #{ <<"service.name">> => <<"my-service">>, <<"service.namespace">> => <<"my-team">>, <<"deployment.environment">> => <<"production">> }}, {traces_exporter, otlp}, {logs_exporter, otlp} ]}, {opentelemetry_exporter, [ {otlp_protocol, http_protobuf}, {otlp_endpoint, "http://localhost:4318"} ]} ]. ``` That's the whole setup. `otlp_endpoint` is a base URL — the exporter appends `/v1/logs` and `/v1/traces` itself. The kernel logger handler is installed when the `opentelemetry` application starts, so make sure it is listed in `extra_applications` (Elixir) or `applications` (Erlang) and starts before your own. Two resource attributes identify the source across all signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Traces are not stored in datasets or collections. View them in Explore Traces, filtering by these resource attributes. The same rule applies if you enable experimental metrics: view them in the Metric Explorer. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. ## Instrument your application Existing `Logger` / `:logger` calls need no changes — the OTel handler runs alongside your console and file handlers. For spans around your own business logic: ```elixir Elixir theme={"dark"} require Logger require OpenTelemetry.Tracer, as: Tracer Tracer.with_span "process-payment" do Tracer.set_attributes([{"payment.amount", 99.99}]) Logger.info("Processing payment") # trace_id and span_id attached automatically end ``` ```erlang Erlang theme={"dark"} ?with_span(<<"process-payment">>, #{}, fun(_SpanCtx) -> ?set_attributes([{<<"payment.amount">>, 99.99}]), ?LOG_INFO("Processing payment") end) ``` Any log emitted inside an active span automatically carries that span's `trace_id` and `span_id`, so you can jump from a log line to its trace in Bronto. ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Traces** — the Explore Traces page If nothing arrives: * Confirm the Collector is running and reachable at `otlp_endpoint`, and that its pipelines include an `otlp` receiver and the Bronto exporters. * Confirm the `opentelemetry` application starts before your own application. * Port `4318` is OTLP/HTTP and `4317` is OTLP/gRPC. If you point at `4317`, set `otlp_protocol: :grpc`. For signal-specific reference material, see [Send Traces to Bronto](/tracing/send-traces). ## Metrics BEAM metrics require the `opentelemetry_experimental` package, which provides the meter and instrument API and a periodic reader. Reuse the same `resource` and OTLP exporter config as above, and check the [OpenTelemetry Erlang/Elixir documentation](https://opentelemetry.io/docs/languages/erlang/) for the instrument API in the release you deploy. An established alternative on the BEAM is to export existing `telemetry` metrics through `TelemetryMetricsPrometheus` and scrape them with the Collector's `prometheus` receiver, which forwards them to Bronto through the same pipeline. See [Send Metrics to Bronto](/metrics/send-metrics). ## Direct export to Bronto Without a Collector, the application exports straight to Bronto over OTLP/HTTP. Point the endpoint at your Bronto region and add your API key: ```elixir Elixir (config/config.exs) theme={"dark"} config :opentelemetry_exporter, otlp_protocol: :http_protobuf, otlp_endpoint: "https://ingestion.eu.bronto.io", # or ingestion.us.bronto.io otlp_headers: [{"x-bronto-api-key", ""}] ``` ```erlang Erlang (sys.config) theme={"dark"} {opentelemetry_exporter, [ {otlp_protocol, http_protobuf}, {otlp_endpoint, "https://ingestion.eu.bronto.io"}, {otlp_headers, [{<<"x-bronto-api-key">>, <<"">>}]} ]} ``` | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector for multi-service environments — it batches, filters, and enriches telemetry, and keeps the API key out of every application. Direct export suits single services and simple architectures. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. ### Manual spans There is no first-party GenAI instrumentation for Erlang or Elixir, so set the attributes yourself around each model call: ```elixir Elixir theme={"dark"} Tracer.with_span "chat gpt-4o-mini" do Tracer.set_attributes([ {"gen_ai.provider.name", "openai"}, {"gen_ai.request.model", "gpt-4o-mini"}, {"gen_ai.usage.input_tokens", 33}, {"gen_ai.usage.output_tokens", 74}, # Bronto flattens array attributes — searchable as finish_reasons.0 {"gen_ai.response.finish_reasons", ["stop"]} ]) end ``` ```erlang Erlang theme={"dark"} ?with_span(<<"chat gpt-4o-mini">>, #{}, fun(_SpanCtx) -> ?set_attributes([ {<<"gen_ai.provider.name">>, <<"openai">>}, {<<"gen_ai.request.model">>, <<"gpt-4o-mini">>}, {<<"gen_ai.usage.input_tokens">>, 33}, {<<"gen_ai.usage.output_tokens">>, 74}, {<<"gen_ai.response.finish_reasons">>, [<<"stop">>]} ]) end) ``` Message content (`gen_ai.input.messages` / `gen_ai.output.messages`) is opt-in by convention and off by default in the languages that have auto-instrumentation. Since you are setting attributes by hand, apply the same discipline — gate prompt and response content behind your own config flag rather than always sending it. See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). # Send Go logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/go Instrument Go applications with the OpenTelemetry Go SDK to send logs, metrics, and traces to Bronto over OTLP/HTTP, via an OTel Collector or directly. One setup function sends **logs, metrics, and traces** from your Go application to Bronto. Logs are bridged from `log/slog`, metrics flow through a meter provider, and traces through a tracer provider — all three sharing one resource identity and one OTLP/HTTP exporter configuration. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — the code is identical, only two environment variables change. ## Prerequisites * Go 1.21 or later (required for `log/slog`) * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Install dependencies ```bash theme={"dark"} go get go.opentelemetry.io/otel \ go.opentelemetry.io/otel/sdk \ go.opentelemetry.io/otel/sdk/log \ go.opentelemetry.io/otel/sdk/metric \ go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp \ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp \ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp \ go.opentelemetry.io/contrib/bridges/otelslog ``` ## Configure the environment The exporters read their endpoint from environment variables, so nothing in the code below is environment-specific. ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318" export OTEL_SERVICE_NAME="my-service" export OTEL_RESOURCE_ATTRIBUTES="service.namespace=my-team,deployment.environment=production" ``` The exporters append the signal path (`/v1/logs`, `/v1/metrics`, `/v1/traces`) to `OTEL_EXPORTER_OTLP_ENDPOINT`, and the URL scheme decides TLS — `http://` for a plaintext local Collector, `https://` for a secured one. Two resource attributes identify the source across all three signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Metrics and traces are not stored in datasets or collections. View them in the Metric Explorer and Explore Traces, filtering by these resource attributes. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. ## Initialise the SDK ```go otel.go theme={"dark"} package main import ( "context" "errors" "log/slog" "go.opentelemetry.io/contrib/bridges/otelslog" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/sdk/log" "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/trace" ) // setupOTel configures logs, metrics, and traces. The returned function flushes // and shuts down all three providers. func setupOTel(ctx context.Context) (func(context.Context) error, error) { // Picks up OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES. res := resource.Default() var shutdownFuncs []func(context.Context) error shutdown := func(ctx context.Context) error { var err error for _, fn := range shutdownFuncs { err = errors.Join(err, fn(ctx)) } return err } // Logs — replace the default slog handler with the OTel bridge. logExporter, err := otlploghttp.New(ctx) if err != nil { return nil, err } loggerProvider := log.NewLoggerProvider( log.WithResource(res), log.WithProcessor(log.NewBatchProcessor(logExporter)), ) slog.SetDefault(slog.New(otelslog.NewHandler("my-service", otelslog.WithLoggerProvider(loggerProvider)))) shutdownFuncs = append(shutdownFuncs, loggerProvider.Shutdown) // Metrics metricExporter, err := otlpmetrichttp.New(ctx) if err != nil { return nil, errors.Join(err, shutdown(ctx)) } meterProvider := metric.NewMeterProvider( metric.WithResource(res), metric.WithReader(metric.NewPeriodicReader(metricExporter)), ) otel.SetMeterProvider(meterProvider) shutdownFuncs = append(shutdownFuncs, meterProvider.Shutdown) // Traces traceExporter, err := otlptracehttp.New(ctx) if err != nil { return nil, errors.Join(err, shutdown(ctx)) } tracerProvider := trace.NewTracerProvider( trace.WithResource(res), trace.WithBatcher(traceExporter), ) otel.SetTracerProvider(tracerProvider) shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) return shutdown, nil } ``` ## Instrument your application Existing `slog` calls need no changes. Add spans and instruments for your own business logic: ```go main.go theme={"dark"} package main import ( "context" "log/slog" "os" "os/signal" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" ) func main() { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) defer stop() shutdown, err := setupOTel(ctx) if err != nil { slog.Error("failed to configure OpenTelemetry", "error", err) os.Exit(1) } defer shutdown(context.Background()) tracer := otel.Tracer("my-service") payments, _ := otel.Meter("my-service").Int64Counter("app.payments") ctx, span := tracer.Start(ctx, "process-payment") span.SetAttributes(attribute.Float64("payment.amount", 99.99)) payments.Add(ctx, 1) slog.InfoContext(ctx, "Processing payment") // trace_id and span_id attached automatically span.End() } ``` Use the `Context`-aware `slog` methods — `InfoContext`, `WarnContext`, `ErrorContext` — and pass the context returned by `tracer.Start`. That is what lets the bridge attach `trace_id` and `span_id`, so you can jump from a log line to its trace in Bronto. Go has no runtime auto-instrumentation. For HTTP servers and clients, wrap your handlers with [`otelhttp`](https://pkg.go.dev/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp); equivalent packages exist for gRPC, `database/sql`, and popular frameworks — see [Go instrumentation libraries](https://opentelemetry.io/docs/languages/go/libraries/). To get traces and RED metrics from Go services with no code changes at all, see [eBPF instrumentation](/opentelemetry/ebpf). ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Metrics** — the Metric Explorer * **Traces** — the Explore Traces page If nothing arrives: * Confirm the Collector is running and reachable at `OTEL_EXPORTER_OTLP_ENDPOINT`, and that its pipelines include an `otlp` receiver and the Bronto exporters. * Confirm the endpoint includes a scheme. Without `http://`, the exporters attempt TLS against a plaintext Collector. * The batch processors export on a background goroutine — keep the `defer shutdown(...)` call so short-lived programs flush before exit. For signal-specific reference material, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). ## Direct export to Bronto Without a Collector, the application exports straight to Bronto over OTLP/HTTP. The code in `otel.go` is unchanged — point the endpoint at your Bronto region and add your API key: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingestion.eu.bronto.io" # or ingestion.us.bronto.io export OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=" ``` | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector for multi-service environments — it batches, filters, and enriches telemetry, and keeps the API key out of every application. Direct export suits single services and simple architectures. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. ### Manual spans There is no first-party GenAI auto-instrumentation package for Go, so set the attributes yourself around each model call: ```go theme={"dark"} tracer := otel.Tracer("my-service") ctx, span := tracer.Start(ctx, "chat gpt-4o-mini") defer span.End() span.SetAttributes( attribute.String("gen_ai.provider.name", "openai"), attribute.String("gen_ai.request.model", "gpt-4o-mini"), attribute.Int("gen_ai.usage.input_tokens", 33), attribute.Int("gen_ai.usage.output_tokens", 74), // Bronto flattens array attributes — this is searchable as finish_reasons.0 attribute.StringSlice("gen_ai.response.finish_reasons", []string{"stop"}), ) ``` Message content (`gen_ai.input.messages` / `gen_ai.output.messages`) is opt-in by convention and off by default in the languages that have auto-instrumentation. Since you are setting attributes by hand, apply the same discipline — gate prompt and response content behind your own config flag rather than always sending it. See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). # Send Java logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/java Instrument Java applications with the OpenTelemetry Java agent to send logs, metrics, and traces to Bronto over OTLP/HTTP, via an OTel Collector or directly. The OpenTelemetry Java agent sends **logs, metrics, and traces** to Bronto with no code changes. Attach it at startup and it instruments Spring, Hibernate, JDBC, Kafka, gRPC, and hundreds of other libraries, bridges your existing Logback or Log4j output into the OTLP logs pipeline, and collects JVM metrics — all under one resource identity. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — only the endpoint and an API key header change. ## Prerequisites * Java 8 or later * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Attach the agent Download the agent jar: ```bash theme={"dark"} curl -L -O https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar ``` Configure it through environment variables and attach it with `-javaagent`: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318" export OTEL_SERVICE_NAME="my-service" export OTEL_RESOURCE_ATTRIBUTES="service.namespace=my-team,deployment.environment=production" java -javaagent:./opentelemetry-javaagent.jar -jar myapp.jar ``` That's the whole setup. The agent exports all three signals over OTLP by default, and agent 2.x uses `http/protobuf`, appending the signal path (`/v1/logs`, `/v1/metrics`, `/v1/traces`) to the endpoint automatically. Two resource attributes identify the source across all three signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Metrics and traces are not stored in datasets or collections. View them in the Metric Explorer and Explore Traces, filtering by these resource attributes. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. Every setting has a system-property equivalent — `-Dotel.service.name=my-service` — if you would rather pass it on the command line. See [Agent configuration](https://opentelemetry.io/docs/zero-code/java/agent/configuration/) for the full list, including how to disable individual instrumentations. ## Instrument your application Existing SLF4J, Logback, and Log4j statements need no changes — the agent picks them up and attaches `trace_id` and `span_id` to any log emitted inside an active span, so you can jump from a log line to its trace in Bronto. For spans and metrics around your own business logic, add the API dependency — not the SDK, which the agent already supplies: ```xml Maven (pom.xml) theme={"dark"} io.opentelemetry opentelemetry-api LATEST ``` ```groovy Gradle (build.gradle) theme={"dark"} // check https://mvnrepository.com/artifact/io.opentelemetry/opentelemetry-api for latest implementation 'io.opentelemetry:opentelemetry-api:LATEST' ``` ```java PaymentService.java theme={"dark"} import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.metrics.LongCounter; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Scope; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PaymentService { private static final Logger logger = LoggerFactory.getLogger(PaymentService.class); private static final Tracer tracer = GlobalOpenTelemetry.getTracer("my-service"); private static final LongCounter payments = GlobalOpenTelemetry.getMeter("my-service") .counterBuilder("app.payments") .build(); public void processPayment(double amount) { Span span = tracer.spanBuilder("process-payment").startSpan(); try (Scope scope = span.makeCurrent()) { span.setAttribute("payment.amount", amount); payments.add(1); logger.info("Processing payment"); // trace_id and span_id attached automatically } finally { span.end(); } } } ``` **Can't use the agent?** Where a javaagent isn't an option — GraalVM native images, for example — build the SDK in process with `opentelemetry-sdk-extension-autoconfigure`, which reads the same `OTEL_*` variables, and add `opentelemetry-logback-appender-1.0` (or `opentelemetry-log4j-appender-2.17`) plus `OpenTelemetryAppender.install(openTelemetry)` to bridge your logs. Spring Boot users can use the [OpenTelemetry Spring Boot starter](https://opentelemetry.io/docs/zero-code/java/spring-boot-starter/) instead. See [Configure the SDK](https://opentelemetry.io/docs/languages/java/configuration/). ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Metrics** — the Metric Explorer * **Traces** — the Explore Traces page If nothing arrives: * Confirm the Collector is running and reachable at `OTEL_EXPORTER_OTLP_ENDPOINT`, and that its pipelines include an `otlp` receiver and the Bronto exporters. * Port `4318` is OTLP/HTTP and `4317` is OTLP/gRPC. If you point at `4317`, also set `OTEL_EXPORTER_OTLP_PROTOCOL=grpc`. * Run with `-Dotel.javaagent.debug=true` to log what the agent instruments and exports at startup. For signal-specific reference material, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). ## Direct export to Bronto Without a Collector, the agent exports straight to Bronto over OTLP/HTTP. Point the endpoint at your Bronto region and add your API key: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingestion.eu.bronto.io" # or ingestion.us.bronto.io export OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=" ``` | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector for multi-service environments — it batches, filters, and enriches telemetry, and keeps the API key out of every application. Direct export suits single services and simple architectures. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. The Java agent includes GenAI instrumentation for the OpenAI Java client and AWS SDK v2 Bedrock calls with no extra dependency. Those model calls produce a span carrying `gen_ai.provider.name`, `gen_ai.request.model`, and token-usage attributes in place of a plain HTTP client span. GenAI coverage in the Java agent is newer and narrower than Python's — check the [agent's supported libraries list](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md) for your provider or framework, and use manual spans below where it isn't covered. ### Capture prompts and responses Content capture is off by default: ```bash theme={"dark"} export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true ``` Depending on the instrumented client and agent version, captured content may be emitted as OTel log records rather than span attributes. It then travels through the logs pipeline, correlated by `trace_id`, and is not queryable on the span itself — to make it searchable alongside the span, emit it as a structured log record following [LLM Observability](/ai-features/llm-observability). ### Manual spans Where the agent doesn't cover your provider, set the same attributes yourself: ```java theme={"dark"} Span span = tracer.spanBuilder("chat gpt-4o-mini").startSpan(); try (Scope scope = span.makeCurrent()) { span.setAttribute("gen_ai.provider.name", "openai"); span.setAttribute("gen_ai.request.model", "gpt-4o-mini"); span.setAttribute("gen_ai.usage.input_tokens", 33); span.setAttribute("gen_ai.usage.output_tokens", 74); // Bronto flattens array attributes — this is searchable as finish_reasons.0 span.setAttribute( AttributeKey.stringArrayKey("gen_ai.response.finish_reasons"), List.of("stop")); } finally { span.end(); } ``` See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). # Send Kotlin logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/kotlin Instrument Kotlin and JVM apps with the OpenTelemetry Java agent to send logs, metrics, and traces to Bronto over OTLP/HTTP, directly or via a Collector. Kotlin runs on the JVM, so the OpenTelemetry Java agent instruments it exactly as it does Java. Attach the agent at startup and it sends **logs, metrics, and traces** to Bronto with no code changes — instrumenting Spring, Ktor, Hibernate, JDBC, Kafka, and hundreds of other libraries, bridging your existing Logback or Log4j output into the OTLP logs pipeline, and collecting JVM metrics under one resource identity. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — only the endpoint and an API key header change. ## Prerequisites * Kotlin 1.8 or later, JVM 8 or later * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Attach the agent Download the agent jar: ```bash theme={"dark"} curl -L -O https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar ``` Configure it through environment variables and attach it with `-javaagent`: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318" export OTEL_SERVICE_NAME="my-service" export OTEL_RESOURCE_ATTRIBUTES="service.namespace=my-team,deployment.environment=production" java -javaagent:./opentelemetry-javaagent.jar -jar myapp.jar ``` That's the whole setup. The agent exports all three signals over OTLP by default, and agent 2.x uses `http/protobuf`, appending the signal path (`/v1/logs`, `/v1/metrics`, `/v1/traces`) to the endpoint automatically. Two resource attributes identify the source across all three signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Metrics and traces are not stored in datasets or collections. View them in the Metric Explorer and Explore Traces, filtering by these resource attributes. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. ## Instrument your application Existing SLF4J, Logback, and Log4j statements need no changes — the agent picks them up and attaches `trace_id` and `span_id` to any log emitted inside an active span, so you can jump from a log line to its trace in Bronto. For spans and metrics around your own business logic, add the API dependency — not the SDK, which the agent already supplies: ```kotlin Gradle (build.gradle.kts) theme={"dark"} // check https://mvnrepository.com/artifact/io.opentelemetry/opentelemetry-api for latest implementation("io.opentelemetry:opentelemetry-api:LATEST") ``` ```xml Maven (pom.xml) theme={"dark"} io.opentelemetry opentelemetry-api LATEST ``` ```kotlin PaymentService.kt theme={"dark"} import io.opentelemetry.api.GlobalOpenTelemetry import org.slf4j.LoggerFactory private val logger = LoggerFactory.getLogger("PaymentService") private val tracer = GlobalOpenTelemetry.getTracer("my-service") private val payments = GlobalOpenTelemetry.getMeter("my-service") .counterBuilder("app.payments") .build() fun processPayment(amount: Double) { val span = tracer.spanBuilder("process-payment").startSpan() try { span.makeCurrent().use { span.setAttribute("payment.amount", amount) payments.add(1) logger.info("Processing payment") // trace_id and span_id attached automatically } } finally { span.end() } } ``` **Can't use the agent?** Where a javaagent isn't an option — GraalVM native images, for example — build the SDK in process with `opentelemetry-sdk-extension-autoconfigure`, which reads the same `OTEL_*` variables, and add `opentelemetry-logback-appender-1.0` plus `OpenTelemetryAppender.install(openTelemetry)` to bridge your logs. See [Configure the SDK](https://opentelemetry.io/docs/languages/java/configuration/). ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Metrics** — the Metric Explorer * **Traces** — the Explore Traces page If nothing arrives: * Confirm the Collector is running and reachable at `OTEL_EXPORTER_OTLP_ENDPOINT`, and that its pipelines include an `otlp` receiver and the Bronto exporters. * Port `4318` is OTLP/HTTP and `4317` is OTLP/gRPC. If you point at `4317`, also set `OTEL_EXPORTER_OTLP_PROTOCOL=grpc`. * Run with `-Dotel.javaagent.debug=true` to log what the agent instruments and exports at startup. For signal-specific reference material, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). ## Direct export to Bronto Without a Collector, the agent exports straight to Bronto over OTLP/HTTP. Point the endpoint at your Bronto region and add your API key: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingestion.eu.bronto.io" # or ingestion.us.bronto.io export OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=" ``` | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector for multi-service environments — it batches, filters, and enriches telemetry, and keeps the API key out of every application. Direct export suits single services and simple architectures. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. The Java agent covers Kotlin applications too — there is no separate Kotlin package. See [Java: GenAI semantic conventions](/opentelemetry/java#genai-semantic-conventions) for current auto-instrumentation coverage and the content-capture setting. ### Manual spans Where the agent doesn't cover your provider, set the same attributes yourself: ```kotlin theme={"dark"} val span = tracer.spanBuilder("chat gpt-4o-mini").startSpan() try { span.makeCurrent().use { span.setAttribute("gen_ai.provider.name", "openai") span.setAttribute("gen_ai.request.model", "gpt-4o-mini") span.setAttribute("gen_ai.usage.input_tokens", 33) span.setAttribute("gen_ai.usage.output_tokens", 74) // Bronto flattens array attributes — this is searchable as finish_reasons.0 span.setAttribute( AttributeKey.stringArrayKey("gen_ai.response.finish_reasons"), listOf("stop")) } } finally { span.end() } ``` See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). # Send Node.js logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/nodejs Instrument Node.js and JavaScript apps with the OpenTelemetry JS SDK to send logs, metrics, and traces to Bronto over OTLP/HTTP, directly or via a Collector. One preloaded module sends **logs, metrics, and traces** from your Node.js application to Bronto. `NodeSDK` wires all three signals to one resource identity, and the auto-instrumentations package traces Express, Fastify, HTTP, gRPC, and database clients — and bridges Winston and Pino output into the OTLP logs pipeline — with no changes to your application code. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — the code is identical, only two environment variables change. ## Prerequisites * Node.js 18 or later * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Install dependencies ```bash theme={"dark"} npm install \ @opentelemetry/api \ @opentelemetry/sdk-node \ @opentelemetry/auto-instrumentations-node \ @opentelemetry/sdk-logs \ @opentelemetry/sdk-metrics \ @opentelemetry/exporter-logs-otlp-http \ @opentelemetry/exporter-metrics-otlp-http \ @opentelemetry/exporter-trace-otlp-http ``` ## Configure the environment The SDK reads its endpoint and identity from environment variables, so nothing in the code below is environment-specific. ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318" export OTEL_SERVICE_NAME="my-service" export OTEL_RESOURCE_ATTRIBUTES="service.namespace=my-team,deployment.environment=production" ``` The SDK appends the signal path (`/v1/logs`, `/v1/metrics`, `/v1/traces`) to `OTEL_EXPORTER_OTLP_ENDPOINT` automatically. Two resource attributes identify the source across all three signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Metrics and traces are not stored in datasets or collections. View them in the Metric Explorer and Explore Traces, filtering by these resource attributes. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. ## Initialise the SDK ```javascript instrumentation.js theme={"dark"} const { NodeSDK } = require('@opentelemetry/sdk-node'); const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node'); const { BatchLogRecordProcessor } = require('@opentelemetry/sdk-logs'); const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics'); const { OTLPLogExporter } = require('@opentelemetry/exporter-logs-otlp-http'); const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-http'); const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http'); const sdk = new NodeSDK({ traceExporter: new OTLPTraceExporter(), metricReader: new PeriodicExportingMetricReader({ exporter: new OTLPMetricExporter() }), logRecordProcessors: [new BatchLogRecordProcessor(new OTLPLogExporter())], instrumentations: [getNodeAutoInstrumentations()], }); sdk.start(); // Flush pending telemetry on shutdown. process.on('SIGTERM', () => sdk.shutdown().finally(() => process.exit(0))); ``` Preload it so the instrumentations patch your dependencies before they are required: ```bash theme={"dark"} node --require ./instrumentation.js app.js ``` For ESM projects, use `node --import ./instrumentation.mjs app.js` and the `register()` hook — see [Node.js instrumentation setup](https://opentelemetry.io/docs/languages/js/getting-started/nodejs/). ## Instrument your application Existing Winston and Pino calls need no changes — the auto-instrumentations bridge them into the OTLP logs pipeline and attach `trace_id` and `span_id` to any log emitted inside an active span, so you can jump from a log line to its trace in Bronto. For spans and metrics around your own business logic: ```javascript payment.js theme={"dark"} const { metrics, trace } = require('@opentelemetry/api'); const tracer = trace.getTracer('my-service'); const payments = metrics.getMeter('my-service').createCounter('app.payments'); async function processPayment(amount) { return tracer.startActiveSpan('process-payment', async (span) => { span.setAttribute('payment.amount', amount); payments.add(1); logger.info('Processing payment'); // trace_id and span_id attached automatically span.end(); }); } ``` ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Metrics** — the Metric Explorer * **Traces** — the Explore Traces page If nothing arrives: * Confirm the Collector is running and reachable at `OTEL_EXPORTER_OTLP_ENDPOINT`, and that its pipelines include an `otlp` receiver and the Bronto exporters. * Confirm `instrumentation.js` is preloaded with `--require` rather than imported from inside `app.js` — instrumentations must run before the libraries they patch are loaded. * The batch processors export on a background timer. Short-lived scripts can exit before the first flush — call `sdk.shutdown()` before exit. For signal-specific reference material, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). ## Direct export to Bronto Without a Collector, the application exports straight to Bronto over OTLP/HTTP. The code in `instrumentation.js` is unchanged — point the endpoint at your Bronto region and add your API key: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingestion.eu.bronto.io" # or ingestion.us.bronto.io export OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=" ``` | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector for multi-service environments — it batches, filters, and enriches telemetry, and keeps the API key out of every application. Direct export suits single services and simple architectures. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. For OpenAI, add the contrib instrumentation to the `instrumentations` array: ```bash theme={"dark"} npm install @opentelemetry/instrumentation-openai ``` ```javascript instrumentation.js theme={"dark"} const { OpenAIInstrumentation } = require('@opentelemetry/instrumentation-openai'); instrumentations: [getNodeAutoInstrumentations(), new OpenAIInstrumentation()], ``` For **Amazon Bedrock**, no extra package is needed — [`@opentelemetry/instrumentation-aws-sdk`](https://www.npmjs.com/package/@opentelemetry/instrumentation-aws-sdk) implements the GenAI conventions for Bedrock Runtime calls (`Converse`, `InvokeModel`) and is already bundled in `@opentelemetry/auto-instrumentations-node`. Each model call then produces a span such as `chat gpt-4o-mini` in place of a plain HTTP client span: | Attribute | Example | | - | - | | `gen_ai.provider.name` | `openai` | | `gen_ai.request.model` | `gpt-4o-mini` | | `gen_ai.usage.input_tokens` | `33` | | `gen_ai.usage.output_tokens` | `74` | | `gen_ai.response.finish_reasons` | `["stop"]` | Need broader provider or framework coverage? See [OpenLLMetry](/integrations/openllmetry) for supported packages, setup, and content-capture controls. ### Capture prompts and responses Content capture is off by default: ```bash theme={"dark"} export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true ``` The JS contrib instrumentations emit captured content as OTel log records rather than span attributes, so it travels through the logs pipeline correlated by `trace_id` and is not queryable on the span itself. To make it searchable alongside the span, emit it as a structured log record following [LLM Observability](/ai-features/llm-observability). The `OTEL_SEMCONV_STABILITY_OPT_IN` variant used by the Python instrumentations is not read by the JS packages. ### Manual spans Where no instrumentation package exists for your provider, set the same attributes yourself: ```javascript theme={"dark"} tracer.startActiveSpan('chat gpt-4o-mini', (span) => { span.setAttributes({ 'gen_ai.provider.name': 'openai', 'gen_ai.request.model': 'gpt-4o-mini', 'gen_ai.usage.input_tokens': 33, 'gen_ai.usage.output_tokens': 74, // Bronto flattens array attributes — this is searchable as finish_reasons.0 'gen_ai.response.finish_reasons': ['stop'], }); span.end(); }); ``` See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). # Ingest OpenTelemetry data into Bronto Source: https://docs.bronto.io/opentelemetry/overview Instrument applications to send logs, metrics, and distributed traces to Bronto using the OpenTelemetry SDK and Collector over OTLP. The pages in this section show you how to instrument your application with the OpenTelemetry SDK to send **logs, metrics, and traces** to Bronto over OTLP/HTTP. The recommended setup enables all three signals: bridge your existing logging framework, record measurements through a meter provider, and create spans through a tracer provider. ## Two ways to instrument **With the OpenTelemetry SDK.** Add a dependency and a short initialisation block to each service — or, in Java, Kotlin, PHP, and Erlang/Elixir, attach an agent or set a few environment variables and skip the code entirely. This gives you all three signals, custom attributes, and spans around your own business logic. It requires a redeploy per service. That is what the language guides below cover. **With eBPF, and no code at all.** [OpenTelemetry eBPF Instrumentation (OBI)](/opentelemetry/ebpf) attaches to already-running processes and captures HTTP and gRPC traffic from the kernel — producing distributed traces and RED metrics with no SDK, no code change, and no redeploy. It sees the process boundary rather than what happens inside it, so there are no custom attributes and no logs. The two are complementary and share one OTLP pipeline into Bronto, with matching trace IDs. A common pattern is eBPF for immediate breadth across every service, then an SDK in the services that warrant deeper detail. Bronto supports OTLP sums, gauges, summaries, and explicit histograms. Exponential histograms are not supported. For Sum, Summary, and Histogram metrics, the Metric Explorer provides [per-second rate functions](/metrics/explore-metrics#aggregation-functions). Want to see Bronto with real data before instrumenting your own app? [Try Bronto with the OpenTelemetry Demo](/getting-started/otel-demo) — spin up a sample microservices app and route its logs, metrics, and traces into Bronto in minutes. Calling an LLM (OpenAI, Anthropic, Amazon Bedrock, etc.)? Every language page below also has a **GenAI semantic conventions** section covering `gen_ai.*` spans — auto-instrumentation where it exists, manual spans where it doesn't, and the experimental prompt/response capture flags. See [LLM Observability](/ai-features/llm-observability) for how Bronto surfaces that data. ## Choose your language
Python
.NET
Java
Kotlin
Node.js
Go
Ruby
PHP
Erlang / Elixir
Rust
C++
Swift
## How OTel logging works OpenTelemetry provides a **Log Bridge API**. You attach an OTel handler or appender to your existing logging framework — Logback, Python's `logging`, `ILogger`, Winston, and so on. Every log record your application emits passes through the bridge, which enriches it with structured metadata and forwards it to the OTel exporter. **Nothing in your application code changes.** `logger.info()`, `log.warn()`, `console.log()` — all of these keep working exactly as before. ### What the bridge adds Here is the same log event before and after the bridge: ```text Before — plain log output theme={"dark"} Payment failed for user 123 ``` ```json After — OTel log record exported to Bronto theme={"dark"} { "timestamp": "2024-11-14T10:32:05.123456789Z", "severity": "ERROR", "body": "Payment failed for user 123", "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", "span_id": "00f067aa0ba902b7", "resource": { "service.name": "payments-api", "service.namespace": "checkout", "deployment.environment": "production" }, "attributes": { "user.id": "123", "exception.type": "PaymentGatewayError", "exception.message": "Card declined: insufficient funds" } } ``` The `trace_id` and `span_id` were injected automatically because this log was emitted inside a traced request. The `service.name` and `service.namespace` were set once at application startup and are now attached to every log record — no per-statement boilerplate. ## Why it's worth adopting **Automatic trace correlation** When a log is emitted inside a traced request, the active `trace_id` and `span_id` are injected automatically — no manual MDC propagation or context threading needed. In Bronto, `trace_id` is a queryable field. Click it to jump from a log line directly to the corresponding trace. **Structured by default** Every OTel log record follows a defined schema: `timestamp`, `severity`, `body`, `attributes`, `resource`, and `instrumentation_scope`. Not "structured if you remembered to configure JSON output" — structured unconditionally, in a format Bronto understands natively. **Service identity is automatic** `service.name` and `service.namespace` are Resource attributes — set once at SDK initialisation, then attached to every signal that process emits. You do not add them to individual log statements, measurements, or spans. For **logs only**, Bronto also maps them to Dataset and Collection with no extra configuration. Metrics and traces keep these attributes as service identity but are not placed in datasets or collections. **Semantic conventions** OTel defines standard attribute names across all languages: `http.request.method`, `exception.type`, `db.system`, `user.id`, and hundreds more. When all your services use the same attribute names, your Bronto queries work identically regardless of which language or framework emitted the log. **One pipeline for logs, metrics, and traces** Logs, metrics, and traces all flow through the same OTel SDK and Collector. They share one API key and resource identity while using a signal-specific OTLP endpoint. You can enable any subset of signals if a service does not need all three. **Vendor portability** OTLP is an open standard. Switching your observability backend requires changing one endpoint URL, not rewriting instrumentation. **Zero code churn** Adoption is a configuration change, not a refactor. Existing log statements are untouched. ## How OTel signals map to Bronto | Signal | Bronto destination | Dataset and collection behavior | | - | - | - | | Logs | [Log Search](https://app.bronto.io/search) | Stored in a dataset and collection | | Metrics | [Metric Explorer](/metrics/explore-metrics) | Not stored in a dataset or collection | | Traces | [Explore Traces](/tracing/explore-traces) | Not stored in a dataset or collection | Resource attributes provide a shared identity across signals. Their log-storage mapping does not apply to metrics or traces: | OTel concept | Bronto behavior | Scope | | - | - | - | | `service.name` | Service identity; also selects the Dataset | All signals; Dataset mapping is logs only | | `service.namespace` | Service namespace; also selects the Collection | All signals; Collection mapping is logs only | | `trace_id` / `span_id` | Correlates a log record with an active trace | Logs emitted in a traced request | | `severity` | Mapped from OTel `SeverityNumber` to log level | Logs | | `attributes` | Searchable fields on the telemetry item | All signals | | `deployment.environment` | Resource identity and filter | All signals | No Bronto-specific SDK attributes are needed. Standard OTel Resource attributes are sufficient. ### Endpoints | Region | Logs | Metrics | Traces | | - | - | - | - | | EU | `https://ingestion.eu.bronto.io/v1/logs` | `https://ingestion.eu.bronto.io/v1/metrics` | `https://ingestion.eu.bronto.io/v1/traces` | | US | `https://ingestion.us.bronto.io/v1/logs` | `https://ingestion.us.bronto.io/v1/metrics` | `https://ingestion.us.bronto.io/v1/traces` | All requests require the header `x-bronto-api-key: `. See [API Keys](/Account-Management/API-Keys) for how to create one. ## Two ways to get data into Bronto ### Via OTel Collector (recommended) Your application exports to an OTel Collector reachable in its environment, which batches, filters, and forwards to Bronto. The Collector can enrich attributes, route signals to multiple destinations, and apply sampling rules before data leaves your infrastructure. **Best for:** multi-service environments, existing Collector infrastructure, or pipelines that need transformation or fan-out before ingestion. See [Connect Open Telemetry to Bronto](/agent-setup/open-telemetry) for Collector setup. ### Direct export The OTel SDK inside your application exports logs, metrics, and traces directly to Bronto over OTLP/HTTP. No additional components are required. **Best for:** new projects, simple architectures, or teams that want the least possible operational overhead. ## Send only the signals you need The examples in these guides enable logs, metrics, and traces by default. OpenTelemetry configures exporters and pipelines per signal, so you can omit any exporter, provider, or Collector pipeline you do not need. See [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces) for signal-specific reference material. # Send PHP logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/php Instrument PHP apps with the OpenTelemetry PHP SDK and auto-instrumentation to send logs, metrics, and traces to Bronto over OTLP/HTTP or a Collector. The OpenTelemetry PHP SDK builds its providers from environment variables, so **logs, metrics, and traces** reach Bronto with almost no code. The `opentelemetry` extension auto-instruments Laravel, Symfony, Slim, PDO, and HTTP clients, and a Monolog handler bridges your existing log calls into the OTLP logs pipeline. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — the code is identical, only two environment variables change. ## Prerequisites * PHP 8.1 or later, and Composer * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Install dependencies The auto-instrumentation extension is a PECL package: ```bash theme={"dark"} pecl install opentelemetry ``` Add `extension=opentelemetry` to your `php.ini`, then install the SDK and the instrumentation packages for your framework: ```bash theme={"dark"} composer require \ open-telemetry/sdk \ open-telemetry/exporter-otlp \ open-telemetry/opentelemetry-logger-monolog \ open-telemetry/opentelemetry-auto-laravel \ php-http/guzzle7-adapter ``` Replace `opentelemetry-auto-laravel` with the package for your framework — `-symfony`, `-slim`, `-psr18`, `-pdo`, and others. See [PHP instrumentation libraries](https://opentelemetry.io/docs/languages/php/libraries/) for the full list. ## Configure the environment ```bash theme={"dark"} export OTEL_PHP_AUTOLOAD_ENABLED=true export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318" export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf" export OTEL_SERVICE_NAME="my-service" export OTEL_RESOURCE_ATTRIBUTES="service.namespace=my-team,deployment.environment=production" ``` `OTEL_PHP_AUTOLOAD_ENABLED` is what builds the tracer, meter, and logger providers from these variables at startup — without it the SDK stays inert. The exporters append the signal path (`/v1/logs`, `/v1/metrics`, `/v1/traces`) to the endpoint automatically. Two resource attributes identify the source across all three signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Metrics and traces are not stored in datasets or collections. View them in the Metric Explorer and Explore Traces, filtering by these resource attributes. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. ## Bridge your logs Traces and metrics need no code. To route Monolog through the same pipeline, attach the OTel handler to your logger, taking the provider the autoloader already configured: ```php logging.php theme={"dark"} pushHandler(new OtelHandler(Globals::loggerProvider(), Level::Debug)); $logger->pushHandler(new \Monolog\Handler\StreamHandler('php://stdout', Level::Debug)); ``` On Monolog 2, use `Logger::DEBUG` in place of `Level::Debug`. ## Instrument your application Existing Monolog calls need no changes. For spans and instruments around your own business logic: ```php theme={"dark"} getTracer('my-service'); $payments = Globals::meterProvider()->getMeter('my-service')->createCounter('app.payments'); $span = $tracer->spanBuilder('process-payment')->startSpan(); $scope = $span->activate(); try { $span->setAttribute('payment.amount', 99.99); $payments->add(1); $logger->info('Processing payment'); // trace_id and span_id attached automatically } finally { $scope->detach(); $span->end(); } ``` Any log emitted inside an active span automatically carries that span's `trace_id` and `span_id`, so you can jump from a log line to its trace in Bronto. ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Metrics** — the Metric Explorer * **Traces** — the Explore Traces page If nothing arrives: * Confirm `OTEL_PHP_AUTOLOAD_ENABLED=true` is set in the environment the PHP process actually runs in — under PHP-FPM that means the pool config, not your shell. * Confirm the Collector is running and reachable at `OTEL_EXPORTER_OTLP_ENDPOINT`, and that its pipelines include an `otlp` receiver and the Bronto exporters. * Check `php -m | grep opentelemetry` lists the extension — without it, the auto-instrumentation packages do nothing. For signal-specific reference material, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). PHP's request-per-process model means each request exports its own batch. In high-throughput deployments, point the SDK at a local Collector rather than at Bronto directly so batching and retries happen outside the request lifecycle. ## Direct export to Bronto Without a Collector, the application exports straight to Bronto over OTLP/HTTP. Point the endpoint at your Bronto region and add your API key: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingestion.eu.bronto.io" # or ingestion.us.bronto.io export OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=" ``` | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector for multi-service environments — it batches, filters, and enriches telemetry, and keeps the API key out of every application. Direct export suits single services and simple architectures. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. ### Manual spans PHP contrib has OpenAI client instrumentation, but it emits `openai.*` rather than the standard `gen_ai.*` fields. For portable attributes, set them yourself around each model call: ```php theme={"dark"} spanBuilder('chat gpt-4o-mini')->startSpan(); $scope = $span->activate(); try { $span->setAttribute('gen_ai.provider.name', 'openai'); $span->setAttribute('gen_ai.request.model', 'gpt-4o-mini'); $span->setAttribute('gen_ai.usage.input_tokens', 33); $span->setAttribute('gen_ai.usage.output_tokens', 74); // Bronto flattens array attributes — this is searchable as finish_reasons.0 $span->setAttribute('gen_ai.response.finish_reasons', ['stop']); } finally { $scope->detach(); $span->end(); } ``` Message content (`gen_ai.input.messages` / `gen_ai.output.messages`) is opt-in by convention and off by default in the languages that have auto-instrumentation. Since you are setting attributes by hand, apply the same discipline — gate prompt and response content behind your own config flag rather than always sending it. See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). # Send Python logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/python Instrument a Python application with the OpenTelemetry Python SDK to send logs, metrics, and traces to Bronto over OTLP/HTTP, via an OTel Collector or directly. One initialisation block sends **logs, metrics, and traces** from your Python application to Bronto. Logs are bridged from the standard `logging` module, metrics flow through a meter provider, and traces through a tracer provider — all three sharing one resource identity and one OTLP/HTTP exporter configuration. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — the code is identical, only two environment variables change. ## Prerequisites * Python 3.9 or later, and pip * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Install the SDK ```bash theme={"dark"} pip install \ opentelemetry-api \ opentelemetry-sdk \ opentelemetry-exporter-otlp-proto-http ``` ## Configure the environment The SDK reads its endpoint and identity from environment variables, so nothing in the code below is environment-specific. ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318" export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf" export OTEL_SERVICE_NAME="my-service" export OTEL_RESOURCE_ATTRIBUTES="service.namespace=my-team,deployment.environment=production" ``` The SDK appends the signal path (`/v1/logs`, `/v1/metrics`, `/v1/traces`) to `OTEL_EXPORTER_OTLP_ENDPOINT` automatically. Two resource attributes identify the source across all three signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Metrics and traces are not stored in datasets or collections. View them in the Metric Explorer and Explore Traces, filtering by these resource attributes. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. ## Initialise the SDK Add this module to your project and call `configure_otel()` once, before your first log statement or span. ```python otel.py theme={"dark"} import logging from opentelemetry import metrics, trace from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler from opentelemetry.sdk._logs.export import BatchLogRecordProcessor from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor def configure_otel(): # Picks up OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES. resource = Resource.create() # Logs — bridges the standard logging module into OTel. logger_provider = LoggerProvider(resource=resource) logger_provider.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter())) logging.getLogger().addHandler(LoggingHandler(logger_provider=logger_provider)) logging.getLogger().setLevel(logging.INFO) # Metrics reader = PeriodicExportingMetricReader(OTLPMetricExporter()) metrics.set_meter_provider(MeterProvider(resource=resource, metric_readers=[reader])) # Traces tracer_provider = TracerProvider(resource=resource) tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter())) trace.set_tracer_provider(tracer_provider) ``` The handler is attached to the root logger, so every logger in the process inherits it and **existing log statements are unchanged**. Pass a name to `logging.getLogger("my_app")` to instrument only part of your application. ## Instrument your application ```python app.py theme={"dark"} import logging from opentelemetry import metrics, trace from otel import configure_otel configure_otel() logger = logging.getLogger(__name__) tracer = trace.get_tracer("my-service") request_counter = metrics.get_meter("my-service").create_counter("app.requests") with tracer.start_as_current_span("handle-request") as span: span.set_attribute("http.request.method", "GET") request_counter.add(1, {"http.request.method": "GET"}) logger.info("Handling request") # trace_id and span_id attached automatically ``` Any log emitted inside an active span automatically carries that span's `trace_id` and `span_id`, so you can jump from a log line to its trace in Bronto with no manual context propagation. **Framework spans without code changes.** Install `opentelemetry-instrumentation-` (for example `opentelemetry-instrumentation-flask`, `-django`, `-fastapi`, `-sqlalchemy`, `-requests`) and run your app with `opentelemetry-instrument python app.py`. The CLI configures the providers itself from the same `OTEL_*` variables above, so use it *instead of* `otel.py` — and add `opentelemetry-instrumentation-logging` so standard-library logs are still bridged. See [Python zero-code instrumentation](https://opentelemetry.io/docs/zero-code/python/). Using **structlog** or **loguru**? See [Python: structlog / loguru](/opentelemetry/python-structlog-loguru) to route them through the same pipeline. ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Metrics** — the Metric Explorer * **Traces** — the Explore Traces page If nothing arrives: * Confirm the Collector is running and reachable at `OTEL_EXPORTER_OTLP_ENDPOINT`, and that its pipelines include an `otlp` receiver and the Bronto exporters. * The batch processors export on a background thread. Short-lived scripts can exit before the first flush — for those, swap in `SimpleLogRecordProcessor` and `SimpleSpanProcessor`, or call `logger_provider.shutdown()` and `tracer_provider.shutdown()` before exit. For signal-specific reference material, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). ## Direct export to Bronto Without a Collector, the application exports straight to Bronto over OTLP/HTTP. The code in `otel.py` is unchanged — point the endpoint at your Bronto region and add your API key: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingestion.eu.bronto.io" # or ingestion.us.bronto.io export OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=" ``` | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector for multi-service environments — it batches, filters, and enriches telemetry, and keeps the API key out of every application. Direct export suits single services and simple architectures. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. Python has the richest GenAI auto-instrumentation of any OTel SDK. Install the instrumentation for your provider and run under the zero-code wrapper: ```bash theme={"dark"} pip install opentelemetry-instrumentation-openai-v2 # or -botocore for Amazon Bedrock via boto3 opentelemetry-instrument python app.py ``` Each model call then produces a span such as `chat gpt-4o-mini` in place of a plain HTTP client span: | Attribute | Example | | - | - | | `gen_ai.provider.name` | `openai` | | `gen_ai.request.model` | `gpt-4o-mini` | | `gen_ai.usage.input_tokens` | `33` | | `gen_ai.usage.output_tokens` | `74` | | `gen_ai.response.finish_reasons` | `["stop"]` | ### Capture prompts and responses Content capture is off by default. Two environment variables enable it: ```bash theme={"dark"} export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=span_only export OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental ``` `span_only` writes content to `gen_ai.input.messages` and `gen_ai.output.messages` on the span, which Bronto surfaces as searchable trace fields. The legacy `true` setting emits it as separate log records correlated by `trace_id`, where it is not queryable on the span itself — prefer `span_only` where your instrumentation supports it. These conventions are still experimental, so verify the attributes emitted by the version you deploy. ### Manual spans Where no instrumentation package exists for your provider, set the same attributes yourself: ```python theme={"dark"} with tracer.start_as_current_span("chat gpt-4o-mini") as span: span.set_attribute("gen_ai.provider.name", "openai") span.set_attribute("gen_ai.request.model", "gpt-4o-mini") span.set_attribute("gen_ai.usage.input_tokens", 33) span.set_attribute("gen_ai.usage.output_tokens", 74) # Bronto flattens array attributes — this is searchable as finish_reasons.0 span.set_attribute("gen_ai.response.finish_reasons", ["stop"]) ``` See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). For Anthropic and LangChain instrumentation, see [OpenLLMetry](/integrations/openllmetry) and [LangChain](/integrations/langchain). # Send Python structlog and loguru logs to Bronto Source: https://docs.bronto.io/opentelemetry/python-structlog-loguru Route Python structlog and loguru output through the OpenTelemetry Python SDK to send structured application logs to Bronto without rewriting log calls. This page wires the two most popular third-party Python logging libraries — **structlog** and **loguru** — into the OpenTelemetry log pipeline. It builds on the [Python page](/opentelemetry/python): set up the SDK, OTLP exporter, and resource attributes there first. Both approaches reuse the OTel `LoggingHandler`, which also attaches `trace_id` and `span_id` automatically inside an active span. ## structlog Route structlog through the standard library logger (which carries the OTel `LoggingHandler` from the Python page) and render each event as JSON so its key/value pairs reach Bronto as structured fields: ```python theme={"dark"} import structlog structlog.configure( logger_factory=structlog.stdlib.LoggerFactory(), wrapper_class=structlog.stdlib.BoundLogger, processors=[ structlog.contextvars.merge_contextvars, structlog.stdlib.add_log_level, structlog.processors.TimeStamper(fmt="iso"), structlog.processors.JSONRenderer(), ], ) log = structlog.get_logger() log.info("user_login", user_id=123, ip="203.0.113.7") ``` structlog emits the rendered JSON to the stdlib logger, the OTel handler exports it, and Bronto parses the JSON body into searchable fields. For the full processor reference, see [structlog's standard-library docs](https://www.structlog.org/en/stable/standard-library.html). ## loguru loguru bypasses stdlib logging, so add the OTel `LoggingHandler` as a loguru sink. Use `enqueue=True` so logging never blocks your application: ```python theme={"dark"} import logging from loguru import logger from opentelemetry.sdk._logs import LoggingHandler # logger_provider is the one configured on the Python page otel_handler = LoggingHandler(level=logging.NOTSET, logger_provider=logger_provider) logger.add(otel_handler, level="INFO", enqueue=True) logger.info("Payment processed: {amount} {ccy}", amount=99.99, ccy="USD") ``` The `LoggingHandler` reads the active span context, so logs emitted inside a span are correlated to their trace automatically — no manual `trace_id` handling needed. ## Verify in Bronto Open [Search](https://app.bronto.io/search) and filter by the `service.name` you set on the Python page. Emit a log from your app and confirm it appears within a few seconds. ## Troubleshooting * **No logs?** Confirm the base OTel setup from the [Python page](/opentelemetry/python) runs at startup (the `LoggerProvider`, exporter, and root-logger handler). * **structlog output not structured?** Keep `JSONRenderer()` as the final processor and use `structlog.stdlib.LoggerFactory()`. * **loguru logs blocking or lost on exit?** Keep `enqueue=True`, and call `logger.remove()` on shutdown so the queue drains before the process exits. # Send Ruby logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/ruby Instrument Ruby and Rails apps with the OpenTelemetry Ruby SDK to send logs, metrics, and traces to Bronto over OTLP/HTTP, directly or via a Collector. One initialiser sends **logs, metrics, and traces** from your Ruby application to Bronto. `OpenTelemetry::SDK.configure` sets up the shared resource and tracing — instrumenting Rails, Rack, Active Record, Faraday, and Redis through `use_all` — and a logger provider and metric reader add the other two signals. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — the code is identical, only two environment variables change. The Ruby logs and metrics SDKs are newer than tracing and their APIs are still settling. Pin your gem versions and check the [OpenTelemetry Ruby documentation](https://opentelemetry.io/docs/languages/ruby/) for the release you deploy. Tracing is stable. ## Prerequisites * Ruby 3.0 or later, and Bundler * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Install dependencies ```ruby Gemfile theme={"dark"} gem 'opentelemetry-sdk' gem 'opentelemetry-instrumentation-all' gem 'opentelemetry-exporter-otlp' gem 'opentelemetry-logs-sdk' gem 'opentelemetry-exporter-otlp-logs' gem 'opentelemetry-metrics-sdk' gem 'opentelemetry-exporter-otlp-metrics' ``` ```bash theme={"dark"} bundle install ``` ## Configure the environment The exporters read their endpoint and identity from environment variables, so nothing in the code below is environment-specific. ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318" export OTEL_SERVICE_NAME="my-service" export OTEL_RESOURCE_ATTRIBUTES="service.namespace=my-team,deployment.environment=production" ``` The exporters append the signal path (`/v1/logs`, `/v1/metrics`, `/v1/traces`) to `OTEL_EXPORTER_OTLP_ENDPOINT` automatically. Two resource attributes identify the source across all three signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Metrics and traces are not stored in datasets or collections. View them in the Metric Explorer and Explore Traces, filtering by these resource attributes. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. ## Initialise the SDK Load this once at startup — in Rails, as `config/initializers/opentelemetry.rb`: ```ruby otel.rb theme={"dark"} require 'opentelemetry/sdk' require 'opentelemetry/instrumentation/all' require 'opentelemetry/logs/sdk' require 'opentelemetry/metrics/sdk' require 'opentelemetry-exporter-otlp' require 'opentelemetry-exporter-otlp-logs' require 'opentelemetry-exporter-otlp-metrics' # Resource, tracing, and every available instrumentation library. # Service identity comes from OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES. OpenTelemetry::SDK.configure do |c| c.use_all end # Logs logger_provider = OpenTelemetry::SDK::Logs::LoggerProvider.new( resource: OpenTelemetry::SDK::Resources::Resource.create ) logger_provider.add_log_record_processor( OpenTelemetry::SDK::Logs::Export::BatchLogRecordProcessor.new( OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new ) ) OpenTelemetry::Logs.logger_provider = logger_provider # Metrics OpenTelemetry.meter_provider.add_metric_reader( OpenTelemetry::SDK::Metrics::Export::PeriodicMetricReader.new( exporter: OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new ) ) at_exit { logger_provider.shutdown } ``` ## Instrument your application Spans and instruments come from the global providers: ```ruby theme={"dark"} tracer = OpenTelemetry.tracer_provider.tracer('my-service') payments = OpenTelemetry.meter_provider.meter('my-service').create_counter('app.payments') tracer.in_span('process-payment') do |span| span.set_attribute('payment.amount', 99.99) payments.add(1) end ``` **Logs need an explicit bridge.** The official SDK does not yet ship a handler for Ruby's standard `Logger`, so application logs are emitted through the OTel Logs API directly: ```ruby theme={"dark"} logger = OpenTelemetry::Logs.logger_provider.logger(name: 'my-service') logger.on_emit( timestamp: Time.now, severity_number: OpenTelemetry::Logs::SeverityNumber::INFO, severity_text: 'INFO', body: 'Processing payment', attributes: { 'payment.amount' => 99.99 } ) ``` A log emitted inside an active span picks up that span's `trace_id` and `span_id` from the current context. Community bridges for Rails and Sidekiq are in development — until one lands, an alternative is to write JSON logs to a file and tail them with the Collector's `filelog` receiver. ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Metrics** — the Metric Explorer * **Traces** — the Explore Traces page If nothing arrives: * Confirm the Collector is running and reachable at `OTEL_EXPORTER_OTLP_ENDPOINT`, and that its pipelines include an `otlp` receiver and the Bronto exporters. * Confirm the initialiser runs before the first span or log emission. * The batch processors export on a background thread — keep the `at_exit` shutdown so short-lived scripts flush before exit. For signal-specific reference material, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). ## Direct export to Bronto Without a Collector, the application exports straight to Bronto over OTLP/HTTP. The code in `otel.rb` is unchanged — point the endpoint at your Bronto region and add your API key: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingestion.eu.bronto.io" # or ingestion.us.bronto.io export OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=" ``` | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector for multi-service environments — it batches, filters, and enriches telemetry, and keeps the API key out of every application. Direct export suits single services and simple architectures. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. ### Manual spans Ruby has no first-party instrumentation emitting GenAI-semconv spans, so set the attributes yourself around each model call: ```ruby theme={"dark"} tracer = OpenTelemetry.tracer_provider.tracer('my-service') tracer.in_span('chat gpt-4o-mini') do |span| span.set_attribute('gen_ai.provider.name', 'openai') span.set_attribute('gen_ai.request.model', 'gpt-4o-mini') span.set_attribute('gen_ai.usage.input_tokens', 33) span.set_attribute('gen_ai.usage.output_tokens', 74) # Bronto flattens array attributes — this is searchable as finish_reasons.0 span.set_attribute('gen_ai.response.finish_reasons', ['stop']) end ``` Message content (`gen_ai.input.messages` / `gen_ai.output.messages`) is opt-in by convention and off by default in the languages that have auto-instrumentation. Since you are setting attributes by hand, apply the same discipline — gate prompt and response content behind your own config flag rather than always sending it. See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). # Send Rust logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/rust Instrument Rust applications with the OpenTelemetry Rust SDK to send logs, metrics, and traces to Bronto over OTLP/HTTP, via an OTel Collector or directly. One setup function sends **logs, metrics, and traces** from your Rust application to Bronto. Logs are bridged from the `log` crate, metrics flow through a meter provider, and traces through a tracer provider — all three sharing one `Resource`. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — only the endpoint and an API key header change. The OpenTelemetry Rust SDK is still evolving and its builder APIs have changed between releases. Pin your versions and check the [OpenTelemetry Rust documentation](https://opentelemetry.io/docs/languages/rust/) for the release you deploy. ## Prerequisites * Rust 1.70 or later * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Install dependencies ```toml Cargo.toml theme={"dark"} # check https://crates.io/crates/opentelemetry for latest versions opentelemetry = { version = "*", features = ["logs", "metrics", "trace"] } opentelemetry_sdk = { version = "*", features = ["logs", "metrics", "trace", "rt-tokio"] } opentelemetry-otlp = { version = "*", features = ["logs", "metrics", "trace", "http-proto", "reqwest-client"] } opentelemetry-appender-log = "*" opentelemetry-semantic-conventions = "*" log = "0.4" tokio = { version = "1", features = ["full"] } ``` ## Initialise the SDK ```rust otel.rs theme={"dark"} use opentelemetry::{global, KeyValue}; use opentelemetry_appender_log::OpenTelemetryLogBridge; use opentelemetry_otlp::{LogExporter, MetricExporter, SpanExporter, WithExportConfig}; use opentelemetry_sdk::{ logs::SdkLoggerProvider, metrics::SdkMeterProvider, resource::Resource, trace::SdkTracerProvider, }; use opentelemetry_semantic_conventions::resource::{ DEPLOYMENT_ENVIRONMENT_NAME, SERVICE_NAME, SERVICE_NAMESPACE, }; const OTLP_ENDPOINT: &str = "http://localhost:4318"; pub struct Otel { logger_provider: SdkLoggerProvider, meter_provider: SdkMeterProvider, tracer_provider: SdkTracerProvider, } impl Otel { /// Flush and shut down all three providers. pub fn shutdown(&self) { let _ = self.logger_provider.shutdown(); let _ = self.meter_provider.shutdown(); let _ = self.tracer_provider.shutdown(); } } pub fn configure_otel() -> Otel { let resource = Resource::new(vec![ KeyValue::new(SERVICE_NAME, "my-service"), KeyValue::new(SERVICE_NAMESPACE, "my-team"), KeyValue::new(DEPLOYMENT_ENVIRONMENT_NAME, "production"), ]); // Logs — bridge the `log` crate into OTel. let logger_provider = SdkLoggerProvider::builder() .with_resource(resource.clone()) .with_batch_exporter( LogExporter::builder() .with_http() .with_endpoint(format!("{OTLP_ENDPOINT}/v1/logs")) .build() .expect("failed to build OTLP log exporter"), ) .build(); log::set_boxed_logger(Box::new(OpenTelemetryLogBridge::new(&logger_provider))) .expect("failed to set logger"); log::set_max_level(log::LevelFilter::Info); // Metrics let meter_provider = SdkMeterProvider::builder() .with_resource(resource.clone()) .with_periodic_exporter( MetricExporter::builder() .with_http() .with_endpoint(format!("{OTLP_ENDPOINT}/v1/metrics")) .build() .expect("failed to build OTLP metric exporter"), ) .build(); global::set_meter_provider(meter_provider.clone()); // Traces let tracer_provider = SdkTracerProvider::builder() .with_resource(resource) .with_batch_exporter( SpanExporter::builder() .with_http() .with_endpoint(format!("{OTLP_ENDPOINT}/v1/traces")) .build() .expect("failed to build OTLP span exporter"), ) .build(); global::set_tracer_provider(tracer_provider.clone()); Otel { logger_provider, meter_provider, tracer_provider } } ``` Two resource attributes identify the source across all three signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Metrics and traces are not stored in datasets or collections. View them in the Metric Explorer and Explore Traces, filtering by these resource attributes. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. ## Instrument your application Existing `log::info!`, `log::warn!`, and `log::error!` calls need no changes: ```rust main.rs theme={"dark"} mod otel; use log::info; use opentelemetry::{global, trace::{TraceContextExt, Tracer}, KeyValue}; #[tokio::main] async fn main() { let otel = otel::configure_otel(); let tracer = global::tracer("my-service"); let payments = global::meter("my-service").u64_counter("app.payments").build(); tracer.in_span("process-payment", |cx| { cx.span().set_attribute(KeyValue::new("payment.amount", 99.99)); payments.add(1, &[]); info!("Processing payment"); // trace_id and span_id attached automatically }); // Flush buffered telemetry before exit. otel.shutdown(); } ``` Middleware instrumentation for Actix Web, Axum, and Tonic is available through community crates — see the [OpenTelemetry Rust registry](https://opentelemetry.io/ecosystem/registry/?language=rust\&component=instrumentation). ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Metrics** — the Metric Explorer * **Traces** — the Explore Traces page If nothing arrives: * Confirm the Collector is running and reachable at the configured endpoint, and that its pipelines include an `otlp` receiver and the Bronto exporters. * Confirm `configure_otel()` runs before the first `log::` macro or span. * The batch exporters run on background tasks — keep the `shutdown()` call so short-lived programs flush before exit. For signal-specific reference material, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). ## Direct export to Bronto Without a Collector, the application exports straight to Bronto over OTLP/HTTP. Point `OTLP_ENDPOINT` at your Bronto region and add your API key to each exporter: ```rust theme={"dark"} const OTLP_ENDPOINT: &str = "https://ingestion.eu.bronto.io"; // or ingestion.us.bronto.io LogExporter::builder() .with_http() .with_endpoint(format!("{OTLP_ENDPOINT}/v1/logs")) .with_headers(HashMap::from([( "x-bronto-api-key".to_string(), "".to_string(), )])) .build() ``` Apply the same `.with_headers(...)` call to the metric and span exporters. | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector for multi-service environments — it batches, filters, and enriches telemetry, and keeps the API key out of every application. Direct export suits single services and simple architectures. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. ### Manual spans There is no first-party GenAI instrumentation for Rust, so set the attributes yourself around each model call: ```rust theme={"dark"} let tracer = global::tracer("my-service"); tracer.in_span("chat gpt-4o-mini", |cx| { let span = cx.span(); span.set_attribute(KeyValue::new("gen_ai.provider.name", "openai")); span.set_attribute(KeyValue::new("gen_ai.request.model", "gpt-4o-mini")); span.set_attribute(KeyValue::new("gen_ai.usage.input_tokens", 33)); span.set_attribute(KeyValue::new("gen_ai.usage.output_tokens", 74)); // Bronto flattens array attributes — this is searchable as finish_reasons.0 span.set_attribute(KeyValue::new("gen_ai.response.finish_reasons", vec!["stop"])); }); ``` Message content (`gen_ai.input.messages` / `gen_ai.output.messages`) is opt-in by convention and off by default in the languages that have auto-instrumentation. Since you are setting attributes by hand, apply the same discipline — gate prompt and response content behind your own config flag rather than always sending it. See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). # Send Swift logs, metrics, and traces to Bronto Source: https://docs.bronto.io/opentelemetry/swift Instrument iOS, macOS, and server-side Swift apps with the OpenTelemetry Swift SDK to send logs, metrics, and traces to Bronto over OTLP/HTTP. One configuration function sends **logs, metrics, and traces** from your Swift application to Bronto. All three providers share a single `Resource`, so telemetry from the process carries one identity. The application exports to an [OpenTelemetry Collector](/agent-setup/open-telemetry), which forwards to Bronto. If you don't run a Collector, [export directly to Bronto](#direct-export-to-bronto) instead — only the endpoint and an API key header change. The official SDK has no bridge to Apple's `os.Logger` (Unified Logging), and auto-instrumentation coverage is thinner than in other languages. Log records are emitted through the OTel Logs API directly, as shown below. Check the [OpenTelemetry Swift registry](https://opentelemetry.io/ecosystem/registry/?language=swift) for community bridges and `URLSession` instrumentation. ## Prerequisites * Swift 5.7 or later; Xcode 14 or later, or Swift Package Manager on Linux * An OTel Collector reachable from your application, with `logs`, `metrics`, and `traces` pipelines forwarding to Bronto — see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry) ## Install dependencies ```swift Package.swift theme={"dark"} // swift-tools-version: 5.7 import PackageDescription let package = Package( name: "MyApp", dependencies: [ .package( url: "https://github.com/open-telemetry/opentelemetry-swift", from: "1.10.0" ), ], targets: [ .executableTarget( name: "MyApp", dependencies: [ .product(name: "OpenTelemetryApi", package: "opentelemetry-swift"), .product(name: "OpenTelemetrySdk", package: "opentelemetry-swift"), .product(name: "OtlpHttpExporter", package: "opentelemetry-swift"), .product(name: "ResourceExtension", package: "opentelemetry-swift"), ] ), ] ) ``` ## Initialise the SDK Call `configureOtel()` once at startup, before the first span or log emission: ```swift Otel.swift theme={"dark"} import Foundation import OpenTelemetryApi import OpenTelemetrySdk import OtlpHttpExporter import ResourceExtension let otlpEndpoint = "http://localhost:4318" func configureOtel() { let resource = DefaultResources().get() .merging(other: Resource(attributes: [ ResourceAttributes.serviceName.rawValue: AttributeValue.string("my-service"), ResourceAttributes.serviceNamespace.rawValue: AttributeValue.string("my-team"), "deployment.environment": AttributeValue.string("production"), ])) // Logs let logExporter = OtlpHttpLogExporter( endpoint: URL(string: "\(otlpEndpoint)/v1/logs")!) let loggerProvider = LoggerProviderBuilder() .with(resource: resource) .with(processors: [BatchLogRecordProcessor(logRecordExporter: logExporter)]) .build() OpenTelemetry.registerLoggerProvider(loggerProvider: loggerProvider) // Metrics let metricExporter = OtlpHttpMetricExporter( endpoint: URL(string: "\(otlpEndpoint)/v1/metrics")!) let meterProvider = MeterProviderBuilder() .with(resource: resource) .with(reader: PeriodicMetricReaderBuilder(exporter: metricExporter).build()) .build() OpenTelemetry.registerMeterProvider(meterProvider: meterProvider) // Traces let spanExporter = OtlpHttpTraceExporter( endpoint: URL(string: "\(otlpEndpoint)/v1/traces")!) let tracerProvider = TracerProviderBuilder() .with(resource: resource) .add(spanProcessor: BatchSpanProcessor(spanExporter: spanExporter)) .build() OpenTelemetry.registerTracerProvider(tracerProvider: tracerProvider) } ``` The metrics builder names have changed across `opentelemetry-swift` releases. If the metrics block doesn't compile against your version, check the [examples in the opentelemetry-swift repository](https://github.com/open-telemetry/opentelemetry-swift/tree/main/Examples). Two resource attributes identify the source across all three signals. For logs only, they also determine storage: | OTel attribute | All signals | Logs only | | - | - | - | | `service.name` | Identifies the emitting service | Selects the Dataset | | `service.namespace` | Groups related services | Selects the Collection | Metrics and traces are not stored in datasets or collections. View them in the Metric Explorer and Explore Traces, filtering by these resource attributes. `http://localhost:4318` is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector — the Collector holds the Bronto API key. On iOS and macOS apps shipped to users, do not embed a Bronto API key in the binary — it can be extracted. Send telemetry to a Collector or gateway you control, and let it hold the key. ## Instrument your application ```swift main.swift theme={"dark"} import OpenTelemetryApi configureOtel() let logger = OpenTelemetry.instance.loggerProvider .loggerBuilder(instrumentationScopeName: "my-service") .build() let tracer = OpenTelemetry.instance.tracerProvider .get(instrumentationName: "my-service") let payments = OpenTelemetry.instance.meterProvider .get(name: "my-service") .createIntCounter(name: "app.payments") let span = tracer.spanBuilder(spanName: "process-payment").startSpan() span.setAttribute(key: "payment.amount", value: 99.99) payments.add(value: 1) var record = ReadableLogRecord() record.body = AttributeValue.string("Processing payment") record.severity = .info logger.emit(logRecord: record) span.end() ``` A log record emitted inside an active span picks up that span's `trace_id` and `span_id` from the current context, so you can jump from a log line to its trace in Bronto. ## Verify Run your application, then check each signal in Bronto, filtering by the `service.name` you set: * **Logs** — the [Search](https://app.bronto.io/search) page, in the dataset named after your service * **Metrics** — the Metric Explorer * **Traces** — the Explore Traces page If nothing arrives: * Confirm the Collector is running and reachable at the configured endpoint, and that its pipelines include an `otlp` receiver and the Bronto exporters. * Confirm `configureOtel()` runs before the first log or span. * The batch processors export on a background timer — make sure the process does not exit, or the app is not suspended, before the first flush. * On iOS, App Transport Security blocks plaintext HTTP by default. Use an `https://` endpoint, or add a development ATS exception for your local Collector. For signal-specific reference material, see [Send Metrics to Bronto](/metrics/send-metrics) and [Send Traces to Bronto](/tracing/send-traces). ## Direct export to Bronto Without a Collector, the application exports straight to Bronto over OTLP/HTTP. Point the endpoint at your Bronto region and add your API key: ```swift theme={"dark"} let otlpEndpoint = "https://ingestion.eu.bronto.io" // or ingestion.us.bronto.io let logExporter = OtlpHttpLogExporter( endpoint: URL(string: "\(otlpEndpoint)/v1/logs")!, config: OtlpConfiguration(headers: [("x-bronto-api-key", "")])) ``` Apply the same configuration to the metric and span exporters. | Region | Base endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io` | | US | `https://ingestion.us.bronto.io` | See [API Keys](/Account-Management/API-Keys) for how to create a key with ingestion permissions. Prefer the Collector — it batches, filters, and enriches telemetry, and keeps the API key out of the application. For distributed mobile apps that is a security requirement, not just a preference. ## GenAI semantic conventions If your application calls an LLM, OpenTelemetry's [GenAI semantic conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) define `gen_ai.*` span attributes for model, token usage, and prompt and response content. ### Manual spans There is no first-party GenAI instrumentation for Swift, so set the attributes yourself around each model call: ```swift theme={"dark"} let span = tracer.spanBuilder(spanName: "chat gpt-4o-mini").startSpan() span.setAttribute(key: "gen_ai.provider.name", value: "openai") span.setAttribute(key: "gen_ai.request.model", value: "gpt-4o-mini") span.setAttribute(key: "gen_ai.usage.input_tokens", value: 33) span.setAttribute(key: "gen_ai.usage.output_tokens", value: 74) // Bronto flattens array attributes — this is searchable as finish_reasons.0 span.setAttribute(key: "gen_ai.response.finish_reasons", value: AttributeValue.array(AttributeArray(values: [.string("stop")]))) span.end() ``` Message content (`gen_ai.input.messages` / `gen_ai.output.messages`) is opt-in by convention and off by default in the languages that have auto-instrumentation. Since you are setting attributes by hand, apply the same discipline — gate prompt and response content behind your own config flag rather than always sending it. See the [GenAI span conventions](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md) for the full attribute list. For the recommended attribute set and Bronto search queries, see [LLM Observability](/ai-features/llm-observability). # Search Syntax Source: https://docs.bronto.io/query-syntax/search-syntax Query Bronto telemetry with a unified search syntax combining SQL-style expressions, autocomplete, and automatic conversion of free-text searches. Bronto uses a single search syntax for filtering and analyzing your data. It combines SQL-style expressions with autocomplete suggestions in the search bar, so you can build queries interactively or write them directly. Bronto supports a subset of SQL for searching and analyzing your data. ⚠️ This is not full ANSI SQL — advanced features such as subqueries, joins, and complex expressions are not supported. The focus is on simple WHERE-style filtering with comparison, boolean, and pattern-matching operators. The search bar corresponds to the `WHERE` clause of a `SELECT` SQL statement, and can be used to filter the results of your query. For example, you can search your firewall logs for users accessing a specific destination with ``` direction='outbound' AND destination_address='52.214.86.65' ``` which retrieves all events that have an attribute named `direction` with a value equal to `'outbound'` and an attribute `destination_address` equal to `'52.214.86.65'`. The single quotes in the above example are important, as otherwise "`outbound`" would be interpreted as an attribute rather than a string value. Bronto automatically parses the attributes in your data, regardless of whether that data is structured, semi-structured, or completely unstructured. You can view the attributes for an event in the inspector when you click on an event. ## Autocomplete When you click into the search bar, Bronto shows an interactive dropdown with keys and values found in your data. You can use autocomplete to build valid search expressions more quickly, especially when you do not want to type field names or values manually. Autocomplete works within the same search syntax described on this page. There is no separate search mode to switch to. ## Free-text Search Bare words are automatically treated as free-text matches against the raw event content. For example, typing `error` matches events that contain "error" in their text. Bronto also automatically converts simple free-text and attribute-style searches into equivalent search syntax, so existing quick searches continue to work without needing a separate mode. For example: * `error` * `username AND (500 OR 404)` * `host:127.0.0.1` Resource attributes prefixed with `$` are excluded from free-text matching. Reference the key explicitly if you want to search them. ## Reserved Attributes Attributes that begin with `@` are reserved attributes that contain some special information: | **attribute** | | Description | | - | - | - | | @raw | | The full text of a log event in its raw form. | | @origin | | The IP address from which Bronto received the event. | ## Implicit Expansion of Bare Words To make free-text search queries simple and concise, Bronto provides a syntactic sugar that is not part of standard SQL. This means that simply typing `error` in the search bar matches all events that contain "error" in their text. Specifically: any character string that appears on its own is automatically expanded into an `ILIKE` expression that checks whether the string appears anywhere in the event. To search for any event that contains `"username"` as well as either `"500"` or `"404"`, you can query with ``` username AND (500 OR 404) ``` In this example, the query filter is automatically expanded to ``` @raw ILIKE '%username%' AND (@raw ILIKE '%500%' OR @raw ILIKE '%404%') ``` Quoted and unquoted strings behave the same way in this context, so quotes may be omitted (unless the search pattern contains special characters). ## Boolean Operators Boolean operators combine the result of other expressions that return a value of `TRUE`, `FALSE` or `UNKNOWN`. | Boolean Operator | Example | Description | | - | - | - | | `AND` | `expr1 AND expr2` | Combines two expressions and returns `TRUE` when both expressions are `TRUE`. | | `OR` | `expr1 OR expr2` | Combines two expressions and returns `TRUE` when either expressions is `TRUE`. | | `NOT` | `NOT expr` | Negates the result of the expression. | ## Comparison Operators Comparison operators compare one expression or value with another, and return a value of `TRUE`, `FALSE` or `UNKNOWN`. | Comparison Operator | Example | Description | | - | - | - | | `[NOT] LIKE` | `attribute LIKE '%value%'` | Returns `TRUE` if the left operand matches the specified pattern (right operand). The pattern can include regular characters or the `%` wildcard, which matches 0 or more of any character. For example, `attribute LIKE 'foo%'` returns any events that start with "foo". The regular characters specified in the pattern are case sensitive and must match exactly. This operator is only applicable to the `STRING` data type. The result is negated if `NOT` appears before the `LIKE` operator. | | `[NOT] ILIKE` | `attribute ILIKE '%value%'` | Same behaviour as the `LIKE` operator, uppercase/lowercase differences are ignored when matching a pattern. | | = | `attribute = value` | Compares the equality of two expressions. Returns `TRUE` if both expressions are equal to each other. | | \<> | `attribute <> value` | Compares the equality of two expressions. Returns `TRUE` if the left operand is not equal to the right operand. | | != | `attribute != value` | Same as the `<>` operator. Compares the equality of two expressions. Returns `TRUE` if the left operand is not equal to the right operand. | | \< | `attribute < value` | Compares two expressions. Returns `TRUE` if the left operand has a lower value than the right operand, otherwise the result is `False`. | | \<= | `attribute <= value` | Compares two expressions. Returns `TRUE` if the left operand has a value lower than or equal to the right operand, otherwise the result is `False`. | | > | `attribute > value` | Compares two expressions. Returns `TRUE` if the left operand has a greater value than the right operand, otherwise the result is `False`. | | >= | `attribute >= value` | Compares two expressions. Returns `TRUE` if the left operand has a value greater than or equal to the right operand, otherwise the result is `False`. | | `IS [NOT] NULL` | `attribute IS NULL` | Returns `TRUE` when the expression evaluates to `NULL`, for example, `myAttribute IS NULL` will return `TRUE` if an event does not contain an attribute with the name `myAttribute`. The `IS NOT NULL`  operator is equivalent to  `NOT  IS NULL` . | ## Operator Precedence When an expression has multiple operators, the operator precedence determines the sequence of operations. Operators have the precedence level shown in the table below, with level `1` being the highest precedence, and `4` being the lowest. An operator with a higher precedence is evaluated before an operator with a lower precedence. | **Level** | Operators | | - | - | | 1 | `=`, `!=`, `<>`, `<`, `>`, `<=`, `>=` | | 2 | `[NOT] LIKE`, `[NOT] ILIKE`, `IS [NOT] NULL` | | 3 | `NOT` | | 4 | `AND` | | 5 | `OR` | Use parentheses to override the defined operator precedence in an expression. ## Quoting & Escaping In search syntax, different types of quotes serve distinct purposes to ensure your queries work correctly. **Quote Types** | Quote Type | Purpose | Example | | - | - | - | | Single quotes (`''`) | STRING literals (values) | `'error'` | | Double quotes (`""`) | Attribute names | `"status_code"` | ### Using Quotes Correctly **STRING Literals** Always use single quotes around values: ``` 'error' 'timeout exceeded' 'ireland' ``` **Attributes** Wrap attributes in double quotes: ``` "status_code" "geo_country" "request-time" ``` Unquoted strings of characters are always interpreted as attributes. However, if your attribute contains any of the following special characters, you **must** wrap it in double quotes: ``` '=' '!' '?' '.' ',' '<' '>' '-' '+' '*' '/' '%' '^' '&' '|' ``` For example: ``` "request-time"='500ms' ``` In this example, `"request-time"` refers to an attribute that includes a dash (`-`). ### Escaping Quotes Quotation marks (both single `'` and double `"`) can be escaped by doubling them up, for example `'O''Brien'` is a `STRING` literal with an apostrophe (`O'Brien`). ## Data Types & Conversions ### Supported Data Types Any expression in a query has a related data type which defines how they will be treated by operators. | Data type | Description | Literal Value | | - | - | - | | `NUMERIC` | Exact number data type for integer data. Valid for integers in the range `-2^63` to `2^63-1`. | Any unquoted sequence of digits. | | `DOUBLE` | Approximate number data type for decimal data. Precise to 15 significant decimal digits. | Any unquoted sequence of digits with a single `.` character anywhere in that sequence. | | `STRING` | Data type for variable length character strings that can consist of letters, numbers, and symbols. | Any sequence of characters surrounded by single quotes. | ### Implicit Data Type Conversions Bronto automatically converts a value from one data type to another when such a conversion makes sense, for example, if your event has an attribute `duration=0.1291` it will match both `duration<1` (`LONG` literal) and `duration<'1'` (`STRING` literal). The rules for implicit data type conversion for binary operators are as follows: | **Precedence** | **Condition** | Implicit Conversion | | - | - | - | | 1 | Both sides are attributes. | No implicit conversion takes place. | | 2 | One side is of type `DOUBLE` and the other side can be converted to `DOUBLE`. | Other side converted to `DOUBLE`. | | 3 | One side is of type `LONG` and the other side can be converted to `LONG`. | Other side converted to `LONG`. | | 4 | One side is an attribute with a `STRING` value and the other side is of type `LONG` or `DOUBLE`. | No implicit conversion takes place. Due to the schemaless nature of Bronto it is possible for an attribute to hold values with differing datatypes. This rule exists to avoid lexicographical `STRING` comparison when a numerical comparison was intended, for example, this means that if your event has attribute `duration` equal to `'null'` then `duration>100` will NOT return `TRUE` (as it would under a lexicographical string comparison). | | 5 | One side is of type `STRING`. | Other side is converted to `STRING`. | | 6 | None of the previous conditions match. | No implicit conversion takes place. | ## String & Text Functions String functions perform operations on a string input value and return a string or numeric value. Bronto supports the following string functions. | **Function** | **Example** | Description | | - | - | - | | `LOWER` | `LOWER('Error')` | Returns a string after converting any uppercase characters to lowercase. The function can be applied to a constant string or a column. | ## Regular Expressions Regular expression operators are an early access feature and are disabled by default. Contact Support if you’d like to enable this feature for your account. Use is subject to our fair use policy. Regular expressions provide a powerful and flexible way to perform pattern matching. Compared to simple string matching, regex provides rich wildcards such as `.` (any character), `\d` (any number), `\s` (any whitespace), and `[xyz]` (any character that is either `x`, `y` or `z`), and repetition operators: `*` matches a sequence of zero or more string; `+` matches one or more; `?` matches zero or none. For example, the regex `cat*` matches `cat` followed by any characters (or none at all). For example, * `cat.*` matches `"catapult"` * `cat.*` matches `"The cat sat"` * `h[aeiou]llo` matches any of `"hallo", "hello", "hollo"` * `(?i)cat` matches `"cat"`, `"CAT"`, `"cAt"` (`(?i)` is the case-insensitive inline modifier) * `[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}` matches email addresses. The precise regex syntax supported by Bronto is RE2, for which you can find the specification [here](https://github.com/google/re2/wiki/syntax). RE2 does not support some features provided by other regex variants (e.g., PCRE), such as positive and negative lookahead/lookbehind. When using regex to query your data, the regex pattern does not need to match the entire event exactly. For example, the pattern `colou?r` will match the event "My favourite colour is red" - it is not necessary to write `.*colou?r.*`. | **Operator** | **Example** | **Description** | | - | - | - | | `[NOT] REGEXP` | `attribute REGEXP '197\.149\.[12][0-59][0-9]\.[0-2].*'` | Returns `TRUE` if the left operand matches the specified regex pattern (right operand). This operator is only applicable to the `STRING` data type. The result is negated if `NOT` appears before the `REGEXP` operator. | | `[NOT] RLIKE` | `attribute RLIKE '197\.149\.[12][0-59][0-9]\.[0-2].*'` | Same behaviour as the `REGEXP` operator. | | `~` | `attribute ~ value` | Same behaviour as the `REGEXP` operator. | | `!~` | `attribute !~ value` | Same behaviour as the `NOT REGEXP` operator. | | `~*` | `attribute ~* value` | Same behaviour as the `REGEXP` operator, but with a case insensitive modifier. | | `!~*` | `attribute !~* value` | Same behaviour as the `REGEXP` operator, but with a case insensitive modifier. | ### Attribute Parsing With Regex Capture Groups If Bronto has not automatically parsed the attributes in your data (for example, if you have an unstructured custom log format) and you have not set up the GROK parsing rules for your data source, then you can use named regex capture groups to parse attributes in your data. A named capture group is declared by using the following syntax: ``` (?PATTERN) ``` where `PATTERN` is a regex pattern, and `name` denotes the attribute you want to parse. For example, suppose you are working with this unstructured custom log: ``` 20171223-22:15:36:154|Step_ExtSDM|30002312|calculateCaloriesWithCache totalCalories=127032 20171223-22:15:36:157|Step_ExtSDM|30002312|calculateAltitudeWithCache totalAltitude=240 20171223-22:15:36:157|Step_StandReportReceiver|30002312|REPORT : 7019 5011 150346 240 20171223-22:15:36:356|Step_LSC|30002312|onStandStepChanged 3592 20171223-22:15:36:365|Step_LSC|30002312|onExtend:1514038537000 1 0 4 20171223-22:15:36:657|Step_SPUtils|30002312| getTodayTotalDetailSteps = 1514038440000##7019##548365##8661##13406##27180468 20171223-22:15:36:657|Step_SPUtils|30002312|setTodayTotalDetailSteps=1514038440000##7020##548365##8661##13501##27180976 20171223-22:15:36:668|Step_ExtSDM|30002312|calculateCaloriesWithCache totalCalories=127054 20171223-22:15:36:672|Step_ExtSDM|30002312|calculateAltitudeWithCache totalAltitude=240 20171223-22:15:36:673|Step_StandReportReceiver|30002312|REPORT : 7020 5012 150368 240 20171223-22:15:37:351|Step_LSC|30002312|onStandStepChanged 3593 ``` Each event has *some* structure - there are individual fields delimited by the "|" character, specifically: 1. the timestamp, 2. the component name, 3. the process id, 4. an unstructured message. We can parse these attributes at query-time by running the following regex query: ``` @raw REGEXP '^(?.*?)\|(?.*?)\|(?.*?)\|(?.*?)$' ``` Named capture groups may only be used: 1. In aggregate functions, e.g., `count`, `min`, `max`. 2. In the group by clause. 3. For column selection. Named capture groups *cannot* be reused as part of the query filter, for example it is not possible to write a query like ``` pid=30002312 AND @raw REGEXP '^(?.*?)\|(?.*?)\|(?.*?)\|(?.*?)$' ``` Now suppose that we are specifically interested in the events which read `REPORT`: ``` 20171223-22:15:36:157|Step_StandReportReceiver|30002312|REPORT : 7019 5011 150346 240 20171223-22:15:36:673|Step_StandReportReceiver|30002312|REPORT : 7020 5012 150368 240 ``` which contain additional information on: 1. the number of steps, 2. the report number, 3. the total calories burned, 4. the altitude. And suppose we want to find the maximum altitude across some time period. First we could restrict the filter to match only the events which contain "REPORT": ``` @raw LIKE '%REPORT%' AND @raw REGEXP '^(?.*?)\|(?.*?)\|(?.*?)\|(?.*?)$' ``` And then we could use nested capture groups to further parse the message, by changing the `(?.*?)` element to ``` (?REPORT : (?\d+) (?\d+) (?\d+) (?\d+)) ``` so that the full query is now ``` @raw LIKE '%REPORT%' AND @raw REGEXP '^(?.*?)\|(?.*?)\|(?.*?)\|(?REPORT : (?\d+) (?\d+) (?\d+) (?\d+))$' ``` With this regex filter, the new attributes "timestamp", "report\_num", "total\_cals\_burned", and "altitude" become available, and we can easily apply a `max(altitude)` function to our query. ## Limits & Restrictions All queries in Bronto are subject to the following limits: * **Maximum length:** 16,000 characters * **Maximum expressions:** 400 (including boolean expressions, comparisons, and standalone tokens) # Explore Traces Source: https://docs.bronto.io/tracing/explore-traces Explore distributed traces in Bronto to investigate services, operations, latency, errors, and trace volume, then drill into spans and correlated logs. Use Tracing to find slow or failing operations, compare services, and drill from an operation into the traces and logs behind it. Traces appear in this tracing experience, not in log datasets or collections. `service.name` identifies the emitting service and can be used as a trace filter; it does not create a dataset for spans. ## Open Tracing In Bronto, select **Tracing** from the left navigation. Bronto Tracing overview with filters, latency charts, error charts, request volume, and the operation table The Tracing page shows: * filters for services, operations, SQL conditions, duration, and time range * summary charts for latency, errors, and request volume * a table of operations with trace count, error rate, latency, and recent activity If the page is empty, first confirm that your services are sending traces. See [Send Traces to Bronto](/tracing/send-traces). ## Filter traces Use the filters at the top of the page to narrow the operations shown in the table. | Filter | Use it to | | - | - | | Services | Include one or more emitting services, such as `frontend-web`, `cart`, or `recommendation` | | Operations | Include one or more operation names, such as `GET`, `POST`, or an RPC method | | SQL filter | Filter by trace and span fields with expressions such as `status=200 AND method='GET'` | | Duration | Focus on traces in a latency band, such as `< 10ms`, `100ms - 1s`, or `> 10s` | | Time range | Limit the view to a recent window, such as the last 10 minutes | The Services and Operations filters support multiple selections, so you can compare related services or focus on a single endpoint. ## Read the overview charts The charts above the table summarize the currently selected trace set. | Chart | What it shows | | - | - | | Latency Over Time | p50, p95, and p99 latency for matching traces | | Errors Over Time | error percentage over the selected time range | | Requests | request volume over time | Use these charts to spot spikes before drilling into the operation table. For example, a latency spike with steady request volume usually points to slow dependencies, while an error spike may point to a failing route or backend service. ## Use status filters The Tracing page includes quick controls for common status views: * **Error** narrows the view to failing traces. * **OK** narrows the view to successful traces. Use **Error** when investigating failures, then clear it to compare failing traces with normal traffic. ## Search operations Use **Filter operations** above the table to quickly find an operation by name. This is useful when a service emits many operations and you already know the route, RPC method, or job name you want to inspect. ## Read the operation table The operation table groups trace activity by operation. | Column | Meaning | | - | - | | Operation | The route, RPC method, job name, or manually named span operation | | Services | Services that emitted traces for the operation | | Traces | Number of matching traces and recent trace volume trend | | Errors | Error percentage and failing trace count | | Latency | Latency summary for matching traces, including percentile values | Sort the table by trace count, errors, or latency to find the busiest, most broken, or slowest operations first. ## Drill into traces Select an operation row to open the traces behind it. From a trace detail view, use the available trace and span context to inspect timing, errors, attributes, and related logs. This is where you move from "which operation is slow or failing?" to "which span or dependency caused it?" ## Common investigation flows **Find a slow endpoint** 1. Set the time range to the period where users reported slowness. 2. Use the Services filter to choose the affected service. 3. Sort by latency. 4. Open the slow operation and inspect the longest traces. **Find a failing operation** 1. Select the **Error** filter. 2. Sort the table by error rate. 3. Open an operation with a high error percentage. 4. Inspect failing spans and related logs. **Compare related services** 1. Select multiple services from the Services filter. 2. Use the operation table to compare trace volume, error rate, and latency. 3. Use SQL filters to narrow the comparison to a method, status, customer, or other indexed field. # Send Traces to Bronto Source: https://docs.bronto.io/tracing/send-traces Send OpenTelemetry traces to Bronto using OTLP over HTTP or gRPC, exported directly from the OTel SDK or routed through an OpenTelemetry Collector. Bronto accepts OpenTelemetry traces over OTLP. You can export traces directly from an OpenTelemetry SDK, or route them through an OpenTelemetry Collector before forwarding them to Bronto. Bronto recommends enabling logs, metrics, and traces together. If you only need traces, OpenTelemetry lets you enable the trace exporter and pipeline independently. For the combined setup, see [Connect OpenTelemetry Collector to Bronto](/agent-setup/open-telemetry). Traces are not stored in Bronto datasets or collections. Sending traces does not create a dataset, and the `x-bronto-dataset`, `x-bronto-collection`, and `x-bronto-tags` log-routing headers do not organize traces. Use OpenTelemetry resource attributes such as `service.name` to identify trace sources, then view the data in [Explore Traces](/tracing/explore-traces). For complete runtime setup and working examples, use the language guides: [Python](/opentelemetry/python) and [Node.js / JavaScript](/opentelemetry/nodejs). ## Prerequisites Before you begin, make sure you have: * a Bronto API key with the **Ingestion** role * an application instrumented with an OpenTelemetry SDK, or an OpenTelemetry Collector receiving traces * network access to the Bronto ingestion endpoint for your region ## Endpoint and authentication Use the trace endpoint that matches your Bronto region: | Region | Trace endpoint | | - | - | | EU | `https://ingestion.eu.bronto.io/v1/traces` | | US | `https://ingestion.us.bronto.io/v1/traces` | Both endpoints accept OTLP/HTTP over HTTPS on port `443`, in either protobuf (`Content-Type: application/x-protobuf`) or JSON (`Content-Type: application/json`) encoding. Every request must include this header: ```text theme={"dark"} x-bronto-api-key: ``` ## Send traces through an OpenTelemetry Collector If you are using an OpenTelemetry Collector, configure an OTLP receiver and an OTLP/HTTP exporter that targets the Bronto trace endpoint. The example uses the standard Collector receiver ports: `4317` for OTLP/gRPC and `4318` for OTLP/HTTP. A same-host application typically exports OTLP/HTTP traces to `http://localhost:4318/v1/traces`; replace the host, port, protocol, and TLS settings when your deployment differs. ```yaml otel-config.yaml theme={"dark"} receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: exporters: otlphttp/brontotraces: traces_endpoint: https://ingestion.eu.bronto.io/v1/traces compression: none headers: x-bronto-api-key: service: pipelines: traces/bronto: receivers: [otlp] processors: [batch] exporters: [otlphttp/brontotraces] ``` Replace the endpoint with your region and replace `` with your Bronto API key. If your Collector also sends logs and metrics, keep a pipeline for each signal. Traces use `traces_endpoint`, metrics use `metrics_endpoint`, and logs use `logs_endpoint`. ## Send traces directly from an SDK If you do not need a Collector, configure your application's OpenTelemetry SDK to export traces directly to Bronto over OTLP/HTTP. For direct trace export, point your SDK at the regional traces endpoint and include the Bronto API key header: ```bash theme={"dark"} export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://ingestion..bronto.io/v1/traces" export OTEL_EXPORTER_OTLP_TRACES_HEADERS="x-bronto-api-key=" export OTEL_TRACES_EXPORTER="otlp" ``` ## Minimal working examples Bronto has OpenTelemetry setup guides for several languages. If you want a quick starting point, the Python and Node.js guides include SDK setup, resource attributes, exporter configuration, and direct export to Bronto. Configure the OpenTelemetry Python SDK, create spans, and export traces to Bronto. Configure the OpenTelemetry JS SDK, create spans, and export traces to Bronto. ## Verify trace delivery After configuration, verify trace delivery with these checks: 1. Confirm that you are sending traces to the correct regional endpoint. 2. Confirm every request includes `x-bronto-api-key`. 3. Run your application and trigger an operation that creates a span. 4. Open [Explore Traces](/tracing/explore-traces) and filter for the expected `service.name`. 5. Confirm new traces are visible and spans include the attributes you expect. ## Troubleshooting If you do not see traces: * verify the ingestion URL matches your region * verify the `x-bronto-api-key` header is present and valid * confirm your process flushes spans before exit * confirm your exporter is configured for traces, not logs or metrics * check network egress rules allow outbound HTTPS on port `443` ## Next steps Once trace ingestion is working, you can: * add auto-instrumentation for your framework or runtime * capture traces from services you cannot rebuild with [zero-code eBPF instrumentation](/opentelemetry/ebpf) * route telemetry through a shared OpenTelemetry Collector * add metrics through the same SDK and Collector * enrich spans with standard resource attributes * standardize exporter configuration across services To inspect incoming trace data, see [Explore Traces](/tracing/explore-traces). # Welcome to Bronto Source: https://docs.bronto.io/welcome Bronto is the Intelligent Observability Data Platform for the AI era: store, search, and monitor telemetry at scale with no trade-offs on cost or coverage. Welcome to Bronto ## Overview Observability is essential for maintaining system health, detecting security threats, and troubleshooting issues efficiently. As infrastructure scales, it generates an overwhelming volume of logs, metrics and traces, forcing teams to decide which data to retain, archive, or discard. Limiting retention, sampling, or filtering data before ingestion can reduce costs, but often leads to gaps in visibility and the loss of critical insights. Scalable observability should not require these trade-offs. Bronto ensures that organizations can store, search, and monitor all their telemetry — without sacrificing coverage or control over costs. With high-performance search, simple cost transparency, and flexible retention, Bronto provides the scale you need without forcing you to compromise on the data that matters. Bronto also includes AI-native workflows built directly into the platform to help teams move faster from raw data to answers. **[Custom Parser](/core-features/custom-parser)** transforms unstructured observability data into structured, queryable events. **[Hosted MCP](/ai-features/hosted-mcp)** and **[Local MCP](/ai-features/local-mcp)** connect AI agents directly to Bronto datasets and search tools. **[BrontoScope](/ai-features/brontoscope)** automatically investigates error events, surfacing likely causes, impact, and recommended next steps with supporting evidence. ## Get Started Collect events from your hosts and send them to Bronto. Search logs across datasets and collections. Use the Metric Explorer and Explore Traces for those signals. Build dashboards and visualizations from the data collected in Bronto. Detect issues early with real-time alerts and automated monitoring. Turn unstructured telemetry into structured, queryable events. Connect AI clients directly to Bronto's hosted MCP endpoint. Run the Bronto MCP server locally for agent access to Bronto data. Investigate error events automatically with AI-generated analysis. Manage users, permissions, and settings for your organization. Integrate Bronto into your stack with API access and automation.