diff --git a/.betterer.results b/.betterer.results index cd2c8005fe381..23c7a9cb4524b 100644 --- a/.betterer.results +++ b/.betterer.results @@ -2955,7 +2955,9 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "9"], [0, 0, 0, "Unexpected any. Specify a different type.", "10"], [0, 0, 0, "Unexpected any. Specify a different type.", "11"], - [0, 0, 0, "Unexpected any. Specify a different type.", "12"] + [0, 0, 0, "Unexpected any. Specify a different type.", "12"], + [0, 0, 0, "Unexpected any. Specify a different type.", "13"], + [0, 0, 0, "Unexpected any. Specify a different type.", "14"] ], "public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], diff --git a/CHANGELOG.md b/CHANGELOG.md index 80e7c536bb180..f9823cdeeff8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ + + +# 11.1.4 (2024-08-14) + +### Bug fixes + +- **Swagger:** Fixed CVE-2024-6837. + + # 11.1.3 (2024-07-26) diff --git a/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-loki/index.md b/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-loki/index.md index 7a45e25805ac6..90926100c789f 100644 --- a/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-loki/index.md +++ b/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-loki/index.md @@ -42,4 +42,4 @@ We recommend that you remove all permissions for roles and teams that are not re 1. Navigate to Data Source Permissions - Go to the permissions tab of the newly created Loki data source. Here, you'll find the Team LBAC rules section. -For more information on how to setup Team LBAC rules for a Loki data source, [Add Team LBAC rules]({{< relref "./../create-teamlbac-rules/" >}}). +For more information on how to setup Team LBAC rules for a Loki data source, refer to [Create Team LBAC rules for the Loki data source](https://grafana.com/docs/grafana//administration/data-source-management/teamlbac/create-teamlbac-rules/). diff --git a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md index c2b6cf84e4811..ff5156f3df9cb 100644 --- a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md +++ b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md @@ -83,11 +83,8 @@ Grafana-managed rules are the most flexible alert rule type. They allow you to c Multiple alert instances can be created as a result of one alert rule (also known as a multi-dimensional alerting). {{% admonition type="note" %}} -For Grafana Cloud, there are limits on how many Grafana-managed alert rules you can create. These are as follows: - -- Free: 100 alert rules -- Paid: 2000 alert rules - {{% /admonition %}} +For Grafana Cloud, you can create 100 free Grafana-managed alert rules. +{{% /admonition %}} Grafana managed alert rules can only be edited or deleted by users with Edit permissions for the folder storing the rules. @@ -256,7 +253,7 @@ You can configure the alert instance state when its evaluation returns no data: | No Data configuration | Description | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | No Data | The default option. Sets alert instance state to `No data`.
The alert rule also creates a new alert instance `DatasourceNoData` with the name and UID of the alert rule, and UID of the datasource that returned no data as labels. | -| Alerting | Sets alert instance state to `Alerting`. It waits until the [pending period](ref:pending-period) has finished. | +| Alerting | Sets alert instance state to `Alerting`. It transitions from `Pending` to `Alerting` after the [pending period](ref:pending-period) has finished. | | Normal | Sets alert instance state to `Normal`. | | Keep Last State | Maintains the alert instance in its last state. Useful for mitigating temporary issues, refer to [Keep last state](ref:keep-last-state). | @@ -265,7 +262,7 @@ You can also configure the alert instance state when its evaluation returns an e | Error configuration | Description | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Error | The default option. Sets alert instance state to `Error`.
The alert rule also creates a new alert instance `DatasourceError` with the name and UID of the alert rule, and UID of the datasource that returned no data as labels. | -| Alerting | Sets alert instance state to `Alerting`. It waits until the [pending period](ref:pending-period) has finished. | +| Alerting | Sets alert instance state to `Alerting`. It transitions from `Pending` to `Alerting` after the [pending period](ref:pending-period) has finished. | | Normal | Sets alert instance state to `Normal`. | | Keep Last State | Maintains the alert instance in its last state. Useful for mitigating temporary issues, refer to [Keep last state](ref:keep-last-state). | diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-amazon-sns.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-amazon-sns.md new file mode 100644 index 0000000000000..6cd38615744f1 --- /dev/null +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-amazon-sns.md @@ -0,0 +1,57 @@ +--- +canonical: https://grafana.com/docs/grafana/latest/alerting/configure-notifications/manage-contact-points/integrations/configure-amazon-sns/ +description: Configure the Grafana Alerting - Amazon SNS integration to receive alert notifications when your alerts are firing. +keywords: + - grafana + - alerting + - Amazon SNS + - integration +labels: + products: + - cloud + - enterprise + - oss +menuTitle: Amazon SNS +title: Configure Amazon SNS for Alerting +weight: 0 +--- + +# Configure Amazon SNS for Alerting + +Use the Grafana Alerting - Amazon SNS integration to send notifications to Amazon SNS when your alerts are firing. + +## Before you begin + +To configure Amazon SNS to receive alert notifications, complete the following steps. + +1. Create a new topic in https://console.aws.amazon.com/sns. +1. Open the topic and create a new subscription. +1. Choose the protocol HTTPS. +1. Copy the URL. + +For more information, refer to [Amazon SNS documentation](https://docs.aws.amazon.com/sns/latest/dg/welcome.html). + +## Procedure + +To create your Amazon SNS integration in Grafana Alerting, complete the following steps. + +1. Navigate to **Alerts & IRM** -> **Alerting** -> **Contact points**. +1. Click **+ Add contact point**. +1. Enter a contact point name. +1. From the Integration list, select **AWS SNS**. +1. Copy in the URL from above into the **The Amazon SNS API URL** field. +1. Click **Test** to check that your integration works. +1. Click **Save contact point**. + +## Next steps + +The Amazon SNS contact point is ready to receive alert notifications. + +To add this contact point to your alert, complete the following steps. + +1. In Grafana, navigate to **Alerting** > **Alert rules**. +1. Edit or create a new alert rule. +1. Scroll down to the **Configure labels and notifications** section. +1. Under Notifications click **Select contact point**. +1. From the drop-down menu, select the previously created contact point. +1. **Click Save rule and exit**. diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-discord.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-discord.md index 75ad4cdaa94f7..001f751d8c149 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-discord.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-discord.md @@ -13,7 +13,7 @@ labels: - oss menuTitle: Discord title: Configure Discord for Alerting -weight: 10 +weight: 0 --- # Configure Discord for Alerting diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-email.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-email.md index a85be6fe3bfce..8295288797b94 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-email.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-email.md @@ -13,7 +13,7 @@ labels: - oss menuTitle: Email title: Configure email for Alerting -weight: 20 +weight: 0 --- # Configure email for Alerting diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-google-chat.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-google-chat.md index 531167a370dcc..e20a31606e998 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-google-chat.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-google-chat.md @@ -13,7 +13,7 @@ labels: - oss menuTitle: Google Chat title: Configure Google Chat for Alerting -weight: 30 +weight: 0 --- # Configure Google Chat for Alerting diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-oncall.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-oncall.md index 5aab071e1adb4..3cfed955a00d4 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-oncall.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-oncall.md @@ -18,7 +18,7 @@ labels: - oss menuTitle: Grafana OnCall title: Configure Grafana OnCall for Alerting -weight: 40 +weight: 0 --- # Configure Grafana OnCall for Alerting diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-opsgenie.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-opsgenie.md index 47cdf1007be00..0ffa3dcf20e2b 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-opsgenie.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-opsgenie.md @@ -13,7 +13,7 @@ labels: - oss menuTitle: Opsgenie title: Configure Opsgenie for Alerting -weight: 60 +weight: 0 --- # Configure Opsgenie for Alerting diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-slack.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-slack.md index 463fd001241b3..b45e0b6757a4d 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-slack.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-slack.md @@ -13,7 +13,7 @@ labels: - oss menuTitle: Slack title: Configure Slack for Alerting -weight: 80 +weight: 0 refs: nested-policy: - pattern: /docs/grafana/ diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-teams.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-teams.md index 7d829b4ec3702..1141af8db6c2e 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-teams.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-teams.md @@ -13,7 +13,7 @@ labels: - oss menuTitle: Microsoft Teams title: Configure Microsoft Teams for Alerting -weight: 50 +weight: 0 --- # Configure Microsoft Teams for Alerting @@ -22,15 +22,16 @@ Use the Grafana Alerting - Microsoft Teams integration to receive notifications ## Before you begin -To set up Microsoft Teams for integration with Grafana Alerting, you need to create an incoming Webhook. This allows Grafana to send alert notifications to Microsoft Teams channels. +To set up Microsoft Teams for integration with Grafana Alerting, create a new workflow that accepts Webhook requests. This allows Grafana to send alert notifications to Microsoft Teams channels. -### Create an incoming Webhook in Microsoft Teams +### Create a workflow in Microsoft Teams -1. To add an incoming Webhook to a Teams channel, follow the steps in the [Create an Incoming Webhook guide](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=newteams%2Cdotnet#create-an-incoming-webhook). +1. To create a new workflow, follow the steps in [Create flows in Microsoft Teams](https://learn.microsoft.com/en-us/power-automate/teams/teams-app-create). +1. Microsoft provides a template library. You can use the template **Post to a channel when a webhook request is received**. +1. At the end of workflow creation wizard, copy the URL that is provided. - Note: The steps to create incoming Webhooks may vary depending on the version of Microsoft Teams you are using. You can switch between the "New Teams" and "Classic Teams" tabs to view the relevant instructions for your version. - -1. Copy the Webhook URL. +**Note** +If you chose a private channel for the target of the workflow, you need to edit workflow before using it. Expand the step "Send each adaptive card", and then expand action "Post your own adaptive card as the Flow bot to a channel". Change "Post as" to User, and save the workflow. ## Procedure @@ -57,3 +58,7 @@ To add this contact point to your alert, complete the following steps. 1. Under Notifications click **Select contact point**. 1. From the drop-down menu, select the previously created contact point. 1. **Click Save rule and exit**. + +## Troubleshooting + +- If Grafana reports that notification was sent successfully but it was not delivered to the channel, check the workflow's run history. You can find it in the workflow details page. diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-telegram.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-telegram.md index bdabe50ee23ab..89e51d4d13913 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-telegram.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-telegram.md @@ -13,7 +13,7 @@ labels: - oss menuTitle: Telegram title: Configure Telegram for Alerting -weight: 90 +weight: 0 --- # Configure Telegram for Alerting diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/pager-duty.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/pager-duty.md index 1f7e9b1247b55..d6202d7adc495 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/pager-duty.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/pager-duty.md @@ -14,7 +14,7 @@ labels: - oss menuTitle: PagerDuty title: Configure PagerDuty for Alerting -weight: 70 +weight: 0 --- # Configure PagerDuty for Alerting diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md index daf7c80d68b00..9b595566cda3a 100644 --- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md +++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md @@ -21,7 +21,7 @@ labels: - oss menuTitle: Webhook notifier title: Configure the webhook notifier for Alerting -weight: 100 +weight: 0 --- # Configure the webhook notifier for Alerting diff --git a/docs/sources/alerting/fundamentals/alert-rule-evaluation/state-and-health.md b/docs/sources/alerting/fundamentals/alert-rule-evaluation/state-and-health.md index b40aca49dc425..6b516e80a92ff 100644 --- a/docs/sources/alerting/fundamentals/alert-rule-evaluation/state-and-health.md +++ b/docs/sources/alerting/fundamentals/alert-rule-evaluation/state-and-health.md @@ -44,13 +44,13 @@ There are three key components that help you understand how your alerts behave d An alert instance can be in either of the following states: -| State | Description | -| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Normal** | The state of an alert when the condition (threshold) is not met. | -| **Pending** | The state of an alert that has breached the threshold but for less than the [pending period](ref:pending-period). | -| **Alerting** | The state of an alert that has breached the threshold for longer than the [pending period](ref:pending-period). | -| **NoData** | The state of an alert whose query returns no data or all values are null. You can [change the default behavior](/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule/#configure-no-data-and-error-handling). | -| **Error** | The state of an alert when an error or timeout occurred evaluating the alert rule. You can [change the default behavior](/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule/#configure-no-data-and-error-handling). | +| State | Description | +| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Normal** | The state of an alert when the condition (threshold) is not met. | +| **Pending** | The state of an alert that has breached the threshold but for less than the [pending period](ref:pending-period). | +| **Alerting** | The state of an alert that has breached the threshold for longer than the [pending period](ref:pending-period). | +| **NoData** | The state of an alert whose query returns no data or all values are null. You can [change the default behavior of the no data state](#modify-the-no-data-and-error-state). | +| **Error** | The state of an alert when an error or timeout occurred evaluating the alert rule. You can [change the default behavior of the error state](#modify-the-no-data-and-error-state). | {{< figure src="/media/docs/alerting/alert-instance-states-v3.png" caption="Alert instance state diagram" alt="A diagram of the distinct alert instance states and transitions." max-width="750px" >}} @@ -64,18 +64,37 @@ Alert instances will be routed for [notifications](ref:notifications) when they An alert instance is considered stale if its dimension or series has disappeared from the query results entirely for two evaluation intervals. -Stale alert instances that are in the **Alerting**, **NoData**, or **Error** states transition to the **Normal** state as **Resolved**, and include the `grafana_state_reason` annotation with the value **MissingSeries**. They are routed for notifications like other resolved alert instances. +Stale alert instances that are in the **Alerting**, **NoData**, or **Error** states transition to the **Normal** state as **Resolved**. Once transitioned, these resolved alert instances are routed for notifications like other resolved alerts. -### Keep last state +### Modify the no data and error state -The "Keep Last State" option helps mitigate temporary data source issues, preventing alerts from unintentionally firing, resolving, and re-firing. - -In [Configure no data and error handling,](ref:no-data-and-error-handling) you can decide to keep the last state of the alert instance when a `NoData` and/or `Error` state is encountered. Just like normal evaluation, the alert instance transitions from `Pending` to `Alerting` after the pending period has elapsed. +In [Configure no data and error handling](ref:no-data-and-error-handling), you can change the default behaviour when the evaluation returns no data or an error. You can set the alert instance state to `Alerting`, `Normal`, or keep the last state. {{< figure src="/media/docs/alerting/alert-rule-configure-no-data-and-error.png" alt="A screenshot of the `Configure no data and error handling` option in Grafana Alerting." max-width="500px" >}} +#### Keep last state + +The "Keep Last State" option helps mitigate temporary data source issues, preventing alerts from unintentionally firing, resolving, and re-firing. + However, in situations where strict monitoring is critical, relying solely on the "Keep Last State" option may not be appropriate. Instead, consider using an alternative or implementing additional alert rules to ensure that issues with prolonged data source disruptions are detected. +### `grafana_state_reason` annotation + +Occasionally, an alert instance may be in a state that isn't immediately clear to everyone. For example: + +- Stale alert instances in the `Alerting` state transition to the `Normal` state when the series disappear. +- If "no data" handling is configured to transition to a state other than `NoData`. +- If "error" handling is configured to transition to a state other than `Error`. +- If the alert rule is deleted, paused, or updated in some cases, the alert instance also transitions to the `Normal` state. + +In these situations, the evaluation state may differ from the alert state, and it might be necessary to understand the reason for being in that state when receiving the notification. + +The `grafana_state_reason` annotation is included in these situations, providing the reason in the notifications that explain why the alert instance transitioned to its current state. For example: + +- Stale alert instances in the `Normal` state include the `grafana_state_reason` annotation with the value **MissingSeries**. +- If "no data" or "error" handling transitions to the `Normal` state, the `grafana_state_reason` annotation is included with the value **NoData** or **Error**, respectively. +- If the alert rule is deleted or paused, the `grafana_state_reason` is set to **Paused** or **RuleDeleted**. For some updates, it is set to **Updated**. + ### Special alerts for `NoData` and `Error` When evaluation of an alert rule produces state `NoData` or `Error`, Grafana Alerting generates a new alert instance that have the following additional labels: diff --git a/docs/sources/dashboards/create-manage-playlists/index.md b/docs/sources/dashboards/create-manage-playlists/index.md index 20acca7382cc9..85d468377b6aa 100644 --- a/docs/sources/dashboards/create-manage-playlists/index.md +++ b/docs/sources/dashboards/create-manage-playlists/index.md @@ -26,6 +26,10 @@ Grafana automatically scales dashboards to any resolution, which makes them perf You can access the Playlist feature from Grafana's side menu, in the Dashboards submenu. +{{< admonition type="note" >}} +You must have at least Editor role permissions to create and manage playlists. +{{< /admonition >}} + ## Access, share, and control a playlist Use the information in this section to access existing playlists. Start and control the display of a playlist using one of the five available modes. diff --git a/docs/sources/dashboards/create-reports/index.md b/docs/sources/dashboards/create-reports/index.md index b356482d3fc96..425070ce01647 100644 --- a/docs/sources/dashboards/create-reports/index.md +++ b/docs/sources/dashboards/create-reports/index.md @@ -129,6 +129,7 @@ Only organization administrators can create reports by default. You can customiz - If you selected the PDF format option: - Select an orientation for the report: **Portrait** or **Landscape**. - Select a layout for the generated report: **Simple** or **Grid**. The simple layout renders each panel as full-width across the PDF. The grid layout renders the PDF with the same panel arrangement and width as the source dashboard. + - Select a zoom level for the report. Zoom in to enlarge text in your PDF, or zoom out to see more data (like table columns) per panel. - Click **Preview PDF** to view a rendered PDF with the options you selected. 1. Schedule report. - Enter scheduling information. Options vary depending on the frequency selected. diff --git a/docs/sources/dashboards/dashboard-public/index.md b/docs/sources/dashboards/dashboard-public/index.md index 252bdfba6d272..b8101e889026d 100644 --- a/docs/sources/dashboards/dashboard-public/index.md +++ b/docs/sources/dashboards/dashboard-public/index.md @@ -1,7 +1,4 @@ --- -aliases: - - ../features/dashboard/dashboards/ - - dashboard-manage/ labels: products: - cloud diff --git a/docs/sources/dashboards/manage-dashboards/index.md b/docs/sources/dashboards/manage-dashboards/index.md index b65cc0baaeb3e..7a9e7371ceb24 100644 --- a/docs/sources/dashboards/manage-dashboards/index.md +++ b/docs/sources/dashboards/manage-dashboards/index.md @@ -1,6 +1,5 @@ --- aliases: - - ../features/dashboard/dashboards/ - ../panels/working-with-panels/organize-dashboard/ - ../reference/dashboard_folders/ - dashboard-folders/ diff --git a/docs/sources/dashboards/use-dashboards/index.md b/docs/sources/dashboards/use-dashboards/index.md index 084de108a939a..f6eeb47f88a2f 100644 --- a/docs/sources/dashboards/use-dashboards/index.md +++ b/docs/sources/dashboards/use-dashboards/index.md @@ -1,6 +1,5 @@ --- aliases: - - ../features/dashboard/dashboards/ - ../reference/search/ - dashboard-ui/ - dashboard-ui/dashboard-header/ diff --git a/docs/sources/dashboards/variables/add-template-variables/index.md b/docs/sources/dashboards/variables/add-template-variables/index.md index b7769ef6509c1..bcb0780eb5e95 100644 --- a/docs/sources/dashboards/variables/add-template-variables/index.md +++ b/docs/sources/dashboards/variables/add-template-variables/index.md @@ -223,7 +223,7 @@ groupByNode(summarize(movingAverage(apps.$app.$server.counters.requests.count, 5 _Ad hoc filters_ enable you to add key/value filters that are automatically added to all metric queries that use the specified data source. Unlike other variables, you do not use ad hoc filters in queries. Instead, you use ad hoc filters to write filters for existing queries. {{% admonition type="note" %}} -Ad hoc filter variables only work with Prometheus, Loki, InfluxDB, and Elasticsearch data sources. +Not all data sources support ad hoc filters. Examples of those that do include Prometheus, Loki, InfluxDB, and Elasticsearch. {{% /admonition %}} 1. [Enter general options](#enter-general-options). diff --git a/docs/sources/datasources/loki/_index.md b/docs/sources/datasources/loki/_index.md index e8eda35660f4a..1dc0024779db2 100644 --- a/docs/sources/datasources/loki/_index.md +++ b/docs/sources/datasources/loki/_index.md @@ -76,7 +76,7 @@ Once you've added the Loki data source, you can [configure it](#configure-the-da To troubleshoot configuration and other issues, check the log file located at `/var/log/grafana/grafana.log` on Unix systems, or in `/data/log` on other platforms and manual installations. {{% /admonition %}} -## Provision the Loki data source +## Provision the data source You can define and configure the data source in YAML files as part of Grafana's provisioning system. For more information about provisioning, and for available configuration options, refer to [Provisioning Grafana](ref:provisioning-data-sources). diff --git a/docs/sources/datasources/mssql/query-editor/index.md b/docs/sources/datasources/mssql/query-editor/index.md index 154229dbafd11..3a43954fd2399 100644 --- a/docs/sources/datasources/mssql/query-editor/index.md +++ b/docs/sources/datasources/mssql/query-editor/index.md @@ -247,6 +247,10 @@ The resulting table panel: ## Use time series queries +{{< admonition type="note" >}} +Store timestamps in UTC to avoid issues with time shifts in Grafana when using non-UTC timezones. +{{< /admonition >}} + If you set the **Format** setting in the query editor to **Time series**, then the query must have a column named `time` that returns either a SQL datetime or any numeric datatype representing Unix epoch in seconds. Result sets of time series queries must also be sorted by time for panels to properly visualize the result. diff --git a/docs/sources/datasources/prometheus/configure-prometheus-data-source.md b/docs/sources/datasources/prometheus/configure-prometheus-data-source.md index 96c4af2107528..014487ae27798 100644 --- a/docs/sources/datasources/prometheus/configure-prometheus-data-source.md +++ b/docs/sources/datasources/prometheus/configure-prometheus-data-source.md @@ -63,15 +63,19 @@ The first option to configure is the name of your connection: - **Default** - Toggle to select as the default name in dashboard panels. When you go to a dashboard panel this will be the default selected data source. -### HTTP section +### Connection section -- **URL** - The URL of your Prometheus server. If your Prometheus server is local, use ``. If it is on a server within a network, this is the URL with port where you are running Prometheus. Example: ``. +- **Prometheus server URL** - The URL of your Prometheus server. If your Prometheus server is local, use `http://localhost:9090`. If it is on a server within a network, this is the URL with port where you are running Prometheus. Example: `http://prometheus.example.orgname:9090`. -- **Allowed cookies** - Specify cookies by name that should be forwarded to the data source. The Grafana proxy deletes all forwarded cookies by default. +{{< admonition type="note" >}} + +If you're running Grafana and Prometheus together in different container environments, each localhost refers to its own container - if the server URL is localhost:9090, that means port 9090 inside the Grafana container, not port 9090 on the host machine. -- **Timeout** - The HTTP request timeout. This must be in seconds. There is no default, so this setting is up to you. +You should use the IP address of the Prometheus container, or the hostname if you are using Docker Compose. Alternatively, you can consider `http://host.docker.internal:9090`. -### Auth section +{{< /admonition >}} + +### Authentication section There are several authentication methods you can choose in the Authentication section. @@ -99,10 +103,16 @@ Use TLS (Transport Layer Security) for an additional layer of security when work - **Value** - The value of the header. -## Additional settings +## Advanced settings Following are additional configuration options. +### Advanced HTTP settings + +- **Allowed cookies** - Specify cookies by name that should be forwarded to the data source. The Grafana proxy deletes all forwarded cookies by default. + +- **Timeout** - The HTTP request timeout. This must be in seconds. The default is 30 seconds. + ### Alerting - **Manage alerts via Alerting UI** - Toggle to enable `Alertmanager` integration for this data source. @@ -121,12 +131,14 @@ Following are additional configuration options. ### Performance -- **Prometheus type** - The type of your Prometheus server. There are four options: `Prometheus`, `Cortex`, `Thanos`, `Mimir`. +- **Prometheus type** - The type of your Prometheus server. There are four options: `Prometheus`, `Cortex`, `Mimir`, and `Thanos`. -- **Version** Select the version you are using. Once the Prometheus type has been selected, a list of versions auto-populates using the Prometheus [buildinfo](https://semver.org/) API. The `Cortex` Prometheus type does not support this API so you will need to manually add the version. +- **Cache level** - The browser caching level for editor queries. There are four options: `Low`, `Medium`, `High`, or `None`. - **Incremental querying (beta)** - Changes the default behavior of relative queries to always request fresh data from the Prometheus instance. Enable this option to decrease database and network load. +- **Disable recording rules (beta)** - Toggle on to disable the recording rules. Enable this option to improve dashboard performance. + ### Other - **Custom query parameters** - Add custom parameters to the Prometheus query URL. For example `timeout`, `partial_response`, `dedup`, or `max_source_resolution`. Multiple parameters should be concatenated together with an '&'. diff --git a/docs/sources/datasources/tempo/configure-tempo-data-source.md b/docs/sources/datasources/tempo/configure-tempo-data-source.md index 93fe169a7bab9..d16a2a1c82951 100644 --- a/docs/sources/datasources/tempo/configure-tempo-data-source.md +++ b/docs/sources/datasources/tempo/configure-tempo-data-source.md @@ -84,9 +84,9 @@ This video explains how to add data sources, including Loki, Tempo, and Mimir, t ## Trace to logs -![Trace to logs settings](/media/docs/tempo/tempo-trace-to-logs-9-4.png) +The **Trace to logs** setting configures [trace to logs](ref:explore-trace-integration) that's available when you integrate Grafana with Tempo. -The **Trace to logs** setting configures the [trace to logs feature](ref:explore-trace-integration) that is available when you integrate Grafana with Tempo. +![Trace to logs settings](/media/docs/tempo/tempo-trace-to-logs-9-4.png) There are two ways to configure the trace to logs feature: @@ -100,8 +100,9 @@ There are two ways to configure the trace to logs feature: You can also click **Open advanced data source picker** to see more options, including adding a data source. 1. Set start and end time shift. As the logs timestamps may not exactly match the timestamps of the spans in trace it may be necessary to search in larger or shifted time range to find the desired logs. -1. Select which tags to use in the logs query. The tags you configure must be present in the span's attributes or resources for a trace to logs span link to appear. You can optionally configure a new name for the tag. This is useful, for example, if the tag has dots in the name and the target data source does not allow using dots in labels. In that case, you can for example remap `http.status` (the span attribute) to `http_status` (the data source field). "Data source" in this context can refer to Loki, or another log data source. -1. Optionally switch on the **Filter by trace ID** and/or **Filter by span ID** setting to further filter the logs if your logs consistently contain trace or span IDs. +1. Select which tags to use in the logs query. + The tags you configure must be present in the span's attributes or resources for a trace to logs span link to appear. You can optionally configure a new name for the tag. This is useful, for example, if the tag has dots in the name and the target data source does not allow using dots in labels. In that case, you can for example remap `http.status` (the span attribute) to `http_status` (the data source field). "Data source" in this context can refer to Loki, or another log data source. +1. Optional: If your logs consistently trace or span IDs, you can use one or both of the **Filter by trace ID** and **Filter by span ID** settings. ### Configure a custom query @@ -141,19 +142,33 @@ There are two ways to configure the trace to metrics feature: - Use a basic configuration with a default query, or - Configure one or more custom queries where you can use a [template language](ref:variable-syntax) to interpolate variables from the trace or span. -### Simple config +Refer to the Trace to metrics configuration options section to learn about the available options. + +### Set up a simple configuration To use a simple configuration, follow these steps: 1. Select a metrics data source from the **Data source** drop-down. +1. Optional: Change **Span start time shift** and **Span end time shift**. You can change one or both of these settings. The default start time shift is -2 minutes and 2 minutes for end time shift. 1. Optional: Choose any tags to use in the query. If left blank, the default values of `cluster`, `hostname`, `namespace`, `pod`, `service.name` and `service.namespace` are used. The tags you configure must be present in the spans attributes or resources for a trace to metrics span link to appear. You can optionally configure a new name for the tag. This is useful for example if the tag has dots in the name and the target data source doesn't allow using dots in labels. In that case you can for example remap `service.name` to `service_name`. -1. Do not select **Add query**. +1. Don't select **Add query**. 1. Select **Save and Test**. -### Custom queries +### Set up custom queries + +To use custom queries, you need to configure the tags you’d like to include in the linked queries. +For each tag, the key is the span attribute name. +In cases where the attribute name would result in an invalid metrics query or doesn’t exactly match the desired label name, you can enter the label name as the second value. +For example, you could map the attribute `k8s.pod` to the label `pod`. + +You can interpolate the configured tags using the `$__tags` keyword. +For example, when you configure the query `requests_total{$__tags}` with the tags `k8s.pod=pod` and `cluster`, it results in `requests_total{pod="nginx-554b9", cluster="us-east-1"}`. +The label values are dynamically inserted based on the span attributes’ values. + +You can link to any metric you’d like, but metrics for span durations, counts, and errors filtered by service or span are a great starting point. To use custom queries with the configuration, follow these steps: @@ -174,7 +189,7 @@ To use custom queries with the configuration, follow these steps: 1. Select **Save and Test**. -### Configure trace to metrics +### Trace to metrics configuration options | Setting name | Description | | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | diff --git a/docs/sources/explore/_index.md b/docs/sources/explore/_index.md index b7ec03e8f0ab5..0deda3011d3da 100644 --- a/docs/sources/explore/_index.md +++ b/docs/sources/explore/_index.md @@ -10,141 +10,53 @@ labels: - cloud - enterprise - oss +menuTitle: Explore title: Explore weight: 90 +hero: + title: Explore + level: 1 + width: 110 + height: 110 + description: >- + Use Explore to query, collect, and analyze data for detailed real-time data analysis. +cards: + title_class: pt-0 lh-1 + items: + - title: Get started with Explore + href: ./get-started-with-explore/ + description: Get started using Explore to create queries and do real-time analysis on your data. + height: 24 + - title: Query management + href: ./query-management/ + description: Learn how to manage queries in Explore. + height: 24 + - title: Query inspector in Explore + href: ./explore-inspector/ + description: Learn how to use the Query inspector to troubleshoot issues with your queries. + height: 24 + - title: Logs in Explore + href: ./logs-integration/ + description: Learn about working with logs and log data in Explore. + height: 24 + - title: Traces in Explore + href: ./trace-integration/ + description: Learn about working with traces and tracing data in Explore. + height: 24 + - title: Correlations editor in Explore + href: ./correlations-editor-in-explore/ + description: Learn how to create and use Correlations. + height: 24 --- -# Explore +{{< docs/hero-simple key="hero" >}} -Grafana's dashboard UI is all about building dashboards for visualization. Explore strips away the dashboard and panel options so that you can focus on the query. It helps you iterate until you have a working query and then think about building a dashboard. - -> Refer to [Role-based access control]({{< relref "../administration/roles-and-permissions/access-control/" >}}) in Grafana Enterprise to understand how you can control access with role-based permissions. - -If you just want to explore your data and do not want to create a dashboard, then Explore makes this much easier. If your data source supports graph and table data, then Explore shows the results both as a graph and a table. This allows you to see trends in the data and more details at the same time. See also: - -- [Query management in Explore]({{< relref "query-management/" >}}) -- [Logs integration in Explore]({{< relref "logs-integration/" >}}) -- [Trace integration in Explore]({{< relref "trace-integration/" >}}) -- [Explore metrics]({{< relref "explore-metrics/" >}}) -- [Correlations Editor in Explore]({{< relref "correlations-editor-in-explore/" >}}) -- [Inspector in Explore]({{< relref "explore-inspector/" >}}) - -## Start exploring - -{{< youtube id="1q3YzX2DDM4" >}} - -> Refer to [Role-based access Control]({{< relref "../administration/roles-and-permissions/access-control/" >}}) in Grafana Enterprise to understand how you can manage Explore with role-based permissions. - -In order to access Explore, you must have an editor or an administrator role, unless the [viewers_can_edit option]({{< relref "../setup-grafana/configure-grafana/#viewers_can_edit" >}}) is enabled. Refer to [About users and permissions]({{< relref "../administration/roles-and-permissions/" >}}) for more information on what each role has access to. - -{{% admonition type="note" %}} -If you are using Grafana Cloud, open a [support ticket in the Cloud Portal](/profile/org#support) to enable the `viewers_can_edit` option -{{% /admonition %}} - -To access Explore: - -1. Click on the Explore icon on the menu bar. - - An empty Explore tab opens. - - Alternately to start with an existing query in a panel, choose the Explore option from the Panel menu. This opens an Explore tab with the query from the panel and allows you to tweak or iterate in the query outside of your dashboard. - - {{< figure src="/media/docs/grafana/panels-visualizations/screenshot-panel-menu-10.1.png" class="docs-image--no-shadow" max-width= "650px" caption="Screenshot of the panel menu including the Explore option" >}} - -1. Choose your data source from the drop-down in the top left. - - You can also click **Open advanced data source picker** to see more options, including adding a data source (Admins only). - -1. Write the query using a query editor provided by the selected data source. Please check [data sources documentation]({{< relref "../datasources" >}}) to see how to use various query editors. -1. For general documentation on querying data sources in Grafana, see [Query and transform data]({{< relref "../panels-visualizations/query-transform-data" >}}). -1. Run the query using the button in the top right corner. - -## Split and compare - -The split view provides an easy way to compare visualizations side-by-side or to look at related data together on one page. - -To open the split view: - -1. Click the split button to duplicate the current query and split the page into two side-by-side queries. - -It is possible to select another data source for the new query which for example, allows you to compare the same query for two different servers or to compare the staging environment to the production environment. - -{{< figure src="/media/docs/grafana/panels-visualizations/screenshot-explore-split-10.1.png" max-width= "950px" caption="Screenshot of Explore screen split" >}} - -In split view, timepickers for both panels can be linked (if you change one, the other gets changed as well) by clicking on one of the time-sync buttons attached to the timepickers. Linking of timepickers helps with keeping the start and the end times of the split view queries in sync. It ensures that you’re looking at the same time interval in both split panels. - -To close the newly created query, click on the Close Split button. - -## Content outline - -The content outline is a side navigation bar that keeps track of the queries and visualization panels you created in Explore. It allows you to navigate between them quickly. - -The content outline also works in a split view. When you are in split view, the content outline is generated for each pane. - -To open the content outline: - -1. Click the Outline button in the top left corner of the Explore screen. - -You can then click on any panel icon in the content outline to navigate to that panel. - -## Share Explore URLs - -When using Explore, the URL in the browser address bar updates as you make changes to the queries. You can share or bookmark this URL. - -{{% admonition type="note" %}} -Explore may generate relatively long URLs, some tools, like messaging or videoconferencing apps, may truncate messages to a fixed length. In such cases Explore will display a warning message and load a default state. If you encounter issues when sharing Explore links in such apps, you can generate shortened links. See [Share shortened link](#share-shortened-link) for more information. -{{% /admonition %}} - -### Generating Explore URLs from external tools - -Because Explore URLs have a defined structure, you can build a URL from external tools and open it in Grafana. The URL structure is: - -``` -http:///explore?panes=&schemaVersion=&orgId= -``` - -where: - -- `org_id` is the organization ID -- `schema_version` is the schema version (should be set to the latest version which is `1`) -- `panes` is a url-encoded JSON object of panes, where each key is the pane ID and each value is an object matching the following schema: - -``` -{ - datasource: string; // the pane's root datasource UID, or `-- Mixed --` for mixed datasources - queries: { - refId: string; // an alphanumeric identifier for this query, must be unique within the pane, i.e. "A", "B", "C", etc. - datasource: { - uid: string; // the query's datasource UID ie: "AD7864H6422" - type: string; // the query's datasource type-id, i.e: "loki" - } - // ... any other datasource-specific query parameters - }[]; // array of queries for this pane - range: { - from: string; // the start time, in milliseconds since epoch - to: string; // the end time, in milliseconds since epoch - } -} -``` - -{{% admonition type="note" %}} -The `from` and `to` also accept relative ranges defined in [Time units and relative ranges]({{< relref "../dashboards/use-dashboards/#time-units-and-relative-ranges" >}}). -{{% /admonition %}} - -## Share shortened link - -{{% admonition type="note" %}} -Available in Grafana 7.3 and later versions. -{{% /admonition %}} - -The Share shortened link capability allows you to create smaller and simpler URLs of the format /goto/:uid instead of using longer URLs with query parameters. To create a shortened link to the executed query, click the **Share** option in the Explore toolbar. +--- -A shortened link that is not accessed will automatically get deleted after a [configurable period](https://grafana.com/docs/grafana//setup-grafana/configure-grafana/#short_links) (defaulting to seven days). If a link is used at least once, it won't be deleted. +## Overview -### Sharing shortened links with absolute time +Explore is your starting point for querying, analyzing, and aggregating data in Grafana. You can quickly begin creating queries to start analyzing data without having to create a dashboard or customize a visualization. -{{% admonition type="note" %}} -Available in Grafana 10.3 and later versions. -{{% /admonition %}} +## Explore -Short links have two options - keeping relative time (for example, from two hours ago to now) or absolute time (for example, from 8am to 10am). Sharing a shortened link by default will copy the time range selected, relative or absolute. Clicking the dropdown button next to the share shortened link button and selecting one of the options under "Time-Sync URL Links" will allow you to create a short link with the absolute time - meaning anyone receiving the link will see the same data you are seeing, even if they open the link at another time. This will not affect your selected time range. +{{< card-grid key="cards" type="simple" >}} diff --git a/docs/sources/explore/explore-metrics.md b/docs/sources/explore/explore-metrics.md index 6ad02a1d82409..be3fc570f6cd7 100644 --- a/docs/sources/explore/explore-metrics.md +++ b/docs/sources/explore/explore-metrics.md @@ -6,7 +6,8 @@ labels: - oss title: Explore Metrics aliases: -description: This topic describes the Explore Metrics feature +canonical: https://grafana.com/docs/grafana/latest/explore/explore-metrics/ +description: Explore Metrics lets you browse Prometheus-compatible metrics using an intuitive, queryless experience. weight: 200 --- @@ -20,13 +21,15 @@ Explore Metrics is currently in [public preview](/docs/release-life-cycle/). Gra With Explore Metrics, you can: -- easily slice and dice metrics based on their labels, so you can immediately see anomalies and identify issues -- see the right visualization for your metric based on its type (gauge vs. counter, for example) without building it yourself -- surface other metrics relevant to the current metric -- “explore in a drawer” - expand a drawer over a dashboard with more content so you don’t lose your place -- view a history of user steps when navigating through metrics and their filters +- Easily slice and dice metrics based on their labels, so you can immediately see anomalies and identify issues +- See the right visualization for your metric based on its type (gauge vs. counter, for example) without building it yourself +- Surface other metrics relevant to the current metric +- “Explore in a drawer” - expand a drawer over a dashboard with more content so you don’t lose your place +- View a history of user steps when navigating through metrics and their filters +{{< docs/play title="Explore Metrics" url="https://play.grafana.org/explore/metrics/trail?from=now-1h&to=now&var-ds=grafanacloud-demoinfra-prom&var-filters=&refresh=&metricPrefix=all" >}} + You can access Explore Metrics either as a standalone experience or as part of Grafana dashboards. ## Standalone experience diff --git a/docs/sources/explore/get-started-with-explore.md b/docs/sources/explore/get-started-with-explore.md new file mode 100644 index 0000000000000..321bc709cbb4e --- /dev/null +++ b/docs/sources/explore/get-started-with-explore.md @@ -0,0 +1,208 @@ +--- +aliases: + - +keywords: + - explore + - loki + - logs +labels: + products: + - cloud + - enterprise + - oss +title: Get started with Explore +weight: 5 +--- + +# Get started with Explore + +Explore is your gateway for querying, analyzing, and aggregating data in Grafana. It allows you to visually explore and iterate until you develop a working query or set of queries for building visualizations and conducting data analysis. If your data source supports graph and table data, there's no need to create a dashboard, as Explore can display the results in both formats. This facilitates quick, detailed, real-time data analysis. + +With Explore you can: + +- Create visualizations to integrate into your dashboards. +- Create queries using mixed data sources. +- Create multiple queries within a single interface. +- Understand the shape of your data across various data sources. +- Perform real time data exploration and analysis. + +Key features include: + +- Query editor, based on specific data source, to create and iterate queries. +- [Query history](https://grafana.com/docs/grafana//explore/query-management/) to track and maintain your queries. +- [Query inspector](https://grafana.com/docs/grafana//explore/explore-inspector/) to help troubleshoot query performance. + +Watch the following video to get started using Explore: + +{{< youtube id="1q3YzX2DDM4" >}} + +## Before you begin + +In order to access Explore, you must have either the `editor` or `administrator` role, unless the [`viewers_can_edit` option](https://grafana.com/docs/grafana//setup-grafana/configure-grafana/#viewers_can_edit) is enabled. Refer to [Role and permissions](https://grafana.com/docs/grafana//administration/roles-and-permissions/) for more information on what each role can access. + +Refer to [Role-based access control (RBAC)](https://grafana.com/docs/grafana//administration/roles-and-permissions/access-control/) in Grafana Enterprise to understand how you can manage Explore with role-based permissions. + +{{< admonition type="note" >}} +If you are using Grafana Cloud, open a [support ticket in the Cloud Portal](/https://grafana.com/auth/sign-in) to enable the `viewers_can_edit` option. +{{< /admonition >}} + +## Explore elements + +Explore consists of a toolbar, outline, query editor, the ability to add multiple queries, a query history and a query inspector. + +- **Outline** - Keeps track of the queries and visualization panels created in Explore. Refer to [Content outline](#content-outline) for more detail. + +- **Toolbar** - Provides quick access to frequently used tools and settings. + + - **Data source picker** - Select a data source from the dropdown menu, or use absolute time. + - **Split** - Click to compare visualizations side by side. Refer to [Split and compare](#split-and-compare) for additional detail. + - **Add** - Click to add your exploration to a dashboard. You can also use this to declare an incident,create a forecast, detect outliers and to run an investigation. + - **Time picker** - Select a time range form the time picker. You can also enter an absolute time range. Refer to [Time picker](#time-picker) for more information. + - **Run query** - Click to run your query. + +- **Query editor** - Interface where you construct the query for a specific data source. Query editor elements differ based on data source. In order to run queries across multiple data sources you need to select **Mixed** from the data source picker. + +- **+Add query** - Add additional queries. +- **Query history** - Query history contains the list of queries that you created in Explore. Refer to [Query history](/docs/grafana//explore/query-management/#query-history) for detailed information on working with your query history. +- **Query inspector** - Provides detailed statistics regarding your query. Inspector functions as a kind of debugging tool that "inspects" your query. It provides query statistics under **Stats**, request response time under **Query**, data frame details under **{} JSON**, and the shape of your data under **Data**. Refer to [Query inspector in Explore](/docs/grafana/latest/explore/explore-inspector/) for additional information. + +## Access Explore + +To access Explore: + +1. Click on **Explore** in the left side menu. + + To start with an existing query from a dashboard panel, select the Explore option from the Panel menu in the upper right. This opens an Explore page with the panel's query, enabling you to tweak or iterate the query outside your dashboard. + + {{< figure src="/media/docs/grafana/panels-visualizations/screenshot-panel-menu-10.1.png" class="docs-image--no-shadow" caption="Panel menu with Explore option" >}} + +1. Select a data source from the drop-down in the upper left. + +1. Using the query editor provided for the specific data source, begin writing your query. Each query editor differs based on each data source's unique elements. + +Some query editors provide a **Kick start your query** option, which gives you a list of basic pre-written queries. Refer to [Use query editors](https://grafana.com/docs/grafana//datasources/#use-query-editors) to see how to use various query editors. For general information on querying data sources in Grafana, refer to [Query and transform data](https://grafana.com/docs/grafana//panels-visualizations/query-transform-data/). + +Based on specific data source, certain query editors allow you to select the label or labels to add to your query. Labels are fields that consist of key/value pairs representing information in the data. Some data sources allow for selecting fields. + +1. Click **Run query** in the upper right to run your query. + +## Content outline + +The content outline is a side navigation bar that keeps track of the queries and visualizations you created in Explore. It allows you to navigate between them quickly. + +The content outline works in a split view, with a separate outline generated for each pane. + +To open the content outline: + +1. Click the Outline button in the top left corner of the Explore screen. + +You can then click on any panel icon in the content outline to navigate to that panel. + +## Split and compare + +The split view enables easy side-by-side comparison of visualizations or simultaneous viewing of related data on a single page. + +To open the split view: + +1. Click the split button to duplicate the current query and split the page into two side-by-side queries. +1. Run and re-run queries as often as needed. + +You can select a different data source, or different metrics and label filters for the new query, allowing you to compare the same query across two different servers or compare the staging environment with the production environment. + +{{< figure src="/media/docs/grafana/panels-visualizations/screenshot-explore-split-10.1.png" max-width= "950px" caption="Screenshot of Explore screen split" >}} + +You can also link the time pickers for both panels by clicking on one of the time-sync buttons attached to the time pickers. When linked, changing the time in one panel automatically updates the other, keeping the start and end times synchronized. This ensures that both split panels display data for the same time interval. + +Click **Close** to quit split view. + +## Time picker + +Use the time picker to select a time range for your query. The default is **last hour**. You can select a different option from the dropdown or use an absolute time range. You can also change the timezone associated with the query, or use a fiscal year. + +1. Click **Change time settings** to change the timezone or apply a fiscal year. + +Refer to [Set dashboard time range](https://grafana.com/docs/grafana//dashboards/use-dashboards/#set-dashboard-time-range) for more information on absolute and relative time ranges. You can also [control the time range using a URL](https://grafana.com/docs/grafana//dashboards/use-dashboards/#control-the-time-range-using-a-url). + +## Mixed data source + +Select **Mixed** from the data source dropdown to run queries across multiple data sources in the same panel. When you select Mixed, you can select a different data source for each new query that you add. + +## Share Explore URLs + +When using Explore, the URL in the browser address bar updates as you make changes to the queries. You can share or bookmark this URL. + +{{% admonition type="note" %}} +Explore may generate long URLs, which some tools, like messaging or videoconferencing applications, might truncate due to fixed message lengths. In such cases, Explore displays a warning and loads a default state. +If you encounter issues when sharing Explore links in these applications, you can generate shortened links. See [Share shortened link](#share-shortened-link) for more information. +{{% /admonition %}} + +### Generate Explore URLs from external tools + +Because Explore URLs have a defined structure, you can build a URL from external tools and open it in Grafana. The URL structure is: + +``` +http:///explore?panes=&schemaVersion=&orgId= +``` + +where: + +- `org_id` is the organization ID +- `schema_version` is the schema version (should be set to the latest version which is `1`) +- `panes` is a URL-encoded JSON object of panes, where each key is the pane ID and each value is an object matching the following schema: + +``` +{ + datasource: string; // the pane's root datasource UID, or `-- Mixed --` for mixed datasources + queries: { + refId: string; // an alphanumeric identifier for this query, must be unique within the pane, i.e. "A", "B", "C", etc. + datasource: { + uid: string; // the query's datasource UID ie: "AD7864H6422" + type: string; // the query's datasource type-id, i.e: "loki" + } + // ... any other datasource-specific query parameters + }[]; // array of queries for this pane + range: { + from: string; // the start time, in milliseconds since epoch + to: string; // the end time, in milliseconds since epoch + } +} +``` + +{{< admonition type="note" >}} +The `from` and `to` also accept relative ranges defined in [Time units and relative ranges](https://grafana.com/docs/grafana//dashboards/use-dashboards/#time-units-and-relative-ranges). +{{< /admonition >}} + +## Share shortened link + +{{< admonition type="note" >}} +Available in Grafana 7.3 and later versions. +{{< /admonition >}} + +The Share shortened link capability allows you to create smaller and simpler URLs of the format `/goto/:uid` instead of using longer URLs with query parameters. To create a shortened link to the executed query, click the **Share** option in the Explore toolbar. + +A shortened link that's not accessed automatically gets deleted after a [configurable period](https://grafana.com/docs/grafana//setup-grafana/configure-grafana/#short_links), which defaults to seven days. However, if the link is accessed at least once, it will not be deleted. + +### Share shortened links with absolute time + +{{< admonition type="note" >}} +Available in Grafana 10.3 and later versions. +{{< /admonition >}} + +Shortened links have two options: relative time (e.g., from two hours ago to now) or absolute time (e.g., from 8am to 10am). By default, sharing a shortened link copies the selected time range, whether it's relative or absolute. + +To create a short link with an absolute time: + +1. Click the dropdown button next to the share shortened link button. +1. Select one of the options under **Time-Sync URL Links**. + +This ensures that anyone receiving the link will see the same data you see, regardless of when they open it. Your selected time range will remain unaffected. + +## Next steps + +Now that you are familiar with Explore you can: + +- [Build dashboards](https://grafana.com/docs/grafana//dashboards/build-dashboards/) +- Create a wide variety of [visualizations](https://grafana.com/docs/grafana//panels-visualizations/visualizations/) +- [Work with logs](https://grafana.com/docs/grafana//explore/logs-integration/) +- [Work with traces](https://grafana.com/docs/grafana/) +- [Create and use correlations](https://grafana.com/docs/grafana//explore/correlations-editor-in-explore/) diff --git a/docs/sources/explore/logs-integration.md b/docs/sources/explore/logs-integration.md index 34275f90e0349..3e8372e67c36b 100644 --- a/docs/sources/explore/logs-integration.md +++ b/docs/sources/explore/logs-integration.md @@ -16,81 +16,89 @@ weight: 15 Explore is a powerful tool for logging and log analysis. It allows you to investigate logs from different data sources including: -- [Loki]({{< relref "../datasources/loki" >}}) -- [Elasticsearch]({{< relref "../datasources/elasticsearch" >}}) -- [Cloudwatch]({{< relref "../datasources/aws-cloudwatch" >}}) -- [InfluxDB]({{< relref "../datasources/influxdb" >}}) -- [Azure Monitor]({{< relref "../datasources/azure-monitor" >}}) +- [Loki](/docs/grafana//datasources/loki/) +- [Elasticsearch](/docs/grafana//datasources/elasticsearch/) +- [Cloudwatch](/docs/grafana//datasources/aws-cloudwatch/) +- [InfluxDB](/docs/grafana//datasources/influxdb/) +- [Azure Monitor](/docs/grafana//datasources/azure-monitor/) - [ClickHouse](https://github.com/grafana/clickhouse-datasource) With Explore, you can efficiently monitor, troubleshoot, and respond to incidents by analyzing your logs and identifying the root causes. It also helps you to correlate logs with other telemetry signals such as metrics, traces or profiles, by viewing them side-by-side. -The results of log queries are displayed as individual log lines and as a graph showing the logs volume for the selected time period. +The results of log queries display as individual log lines and as a graph showing the logs volume for the selected time period. ## Logs volume -When working with data sources that support a full range logs volume, Explore automatically displays a graph showing the log distribution for all the entered log queries. This feature is currently supported by Elasticsearch and Loki data sources. +When working with data sources that support a full range logs volume, Explore automatically displays a graph showing the log distribution for all submitted log queries. This feature is currently supported by the Elasticsearch and Loki data sources. -> **Note:** In Loki, this full range log volume is rendered by a metric query which can be expensive depending on time range queried. This query can be particularly challenging to process for smaller Loki installations. To mitigate this, we recommend using a proxy like [nginx](https://www.nginx.com/) in front of Loki to set a custom timeout (for example, 10 seconds) for these queries. Log volume histogram queries can be identified by looking for queries with the HTTP header `X-Query-Tags` with value `Source=logvolhist`; these headers are added by Grafana to all log volume histogram queries. +{{< admonition type="note" >}} +In Loki, generating the full range log volume via a metric query can be resource-intensive, depending on the time range queried. This is especially challenging for smaller Loki installations. To mitigate this, we recommend that you use a proxy like [nginx](https://www.nginx.com/) in front of Loki with a timeout like 10ss. Log volume histogram queries can be identified by looking for queries with the HTTP header `X-Query-Tags` with value `Source=logvolhist`; these headers are added by Grafana to all log volume histogram queries. +{{< /admonition >}} -If the data source does not support loading the full range logs volume, the logs model calculates a time series by counting log rows and organizing them into buckets based on an automatically calculated time interval. The timestamp of the first log row is used to anchor the start of the logs volume in the results. The end of the time series is anchored to the time picker's **To** range. This way, you can still analyze and visualize log data efficiently even when the data source doesn't offer full range support. +If the data source doesn't support loading the full range logs volume, the logs model calculates a time series by counting log rows and organizing them into buckets based on an automatically calculated time interval. The timestamp of the first log row is used to anchor the start of the logs volume in the results. The end of the time series is anchored to the time picker's **To** range. This way, you can still analyze and visualize log data efficiently even when the data source doesn't offer full range support. ## Logs -In the following sections, you will find detailed explanations of how to visualize and interact with individual logs in Explore. +The following sections provide detailed explanations on how to visualize and interact with individual logs in Explore. ### Logs navigation -Logs navigation, at the right side of the log lines, can be used to easily request additional logs. You can do this by clicking the **Older logs** button at the bottom of the navigation. This is especially useful when you reach the line limit and you want to see more logs. Each request that is run from the navigation is then displayed in the navigation as separate page. Every page shows `from` and `to` timestamps of the incoming log lines. You can see previous results by clicking on each page. Explore caches the last five requests run from the logs navigation, so you're not re-running the same queries when clicking on the pages, saving time and resources. +Logs navigation, located at the right side of the log lines, can be used to easily request additional logs by clicking **Older logs** at the bottom of the navigation. This is especially useful when you reach the line limit and you want to see more logs. Each request run from the navigation displays in the navigation as separate page. Every page shows `from` and `to` timestamps of the incoming log lines. You can see previous results by clicking on each page. Explore caches the last five requests run from the logs navigation so you're not re-running the same queries when clicking on the pages, saving time and resources. ![Navigate logs in Explore](/static/img/docs/explore/navigate-logs-8-0.png) ### Visualization options -You can customize how logs are displayed and select which columns are shown. +You have the option to customize the display of logs and choose which columns to show. Following is a list of available options. -| Option | Description | -| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Time** | Shows or hides the time column. This is the timestamp associated with the log line as reported from the data source. | -| **Unique labels** | Shows or hides the unique labels column that includes only non-common labels. All common labels are displayed above. | -| **Wrap lines** | Set this to `true` if you want the display to use line wrapping. If set to `false`, it will result in horizontal scrolling. | -| **Prettify JSON** | Set this to `true` to pretty print all JSON logs. This setting does not affect logs in any format other than JSON. | -| **Deduplication** | Log data can be very repetitive and Explore can help by hiding duplicate log lines. There are a few different deduplication algorithms that you can use **Exact** matches are done on the whole line except for date fields. **Numbers** matches are done on the line after stripping out numbers such as durations, IP addresses, and so on. **Signature** is the most aggressive deduplication as it strips all letters and numbers and matches on the remaining whitespace and punctuation. | -| **Display results order** | You can change the order of received logs from the default descending order (newest first) to ascending order (oldest first). | +| Option | Description | +| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Time** | Shows or hides the time column. This is the timestamp associated with the log line as reported from the data source. | +| **Unique labels** | Shows or hides the unique labels column that includes only non-common labels. All common labels are displayed above. | +| **Wrap lines** | Set this to `true` if you want the display to use line wrapping. If set to `false`, it will result in horizontal scrolling. | +| **Prettify JSON** | Set this to `true` to pretty print all JSON logs. This setting does not affect logs in any format other than JSON. | +| **Deduplication** | Log data can be very repetitive. Explore hides duplicate log lines using a few different deduplication algorithms. **Exact** matches are done on the whole line except for date fields. **Numbers** matches are done on the line after stripping out numbers such as durations, IP addresses, and so on. **Signature** is the most aggressive deduplication as it strips all letters and numbers and matches on the remaining whitespace and punctuation. | +| **Display results order** | You can change the order of received logs from the default descending order (newest first) to ascending order (oldest first). | ### Download log lines -To download log results in either `txt` or `json` format, simply use the **Download** button. This feature allows you to save the log data for further analysis or to share it with others in a convenient and accessible format. +Click **Download** to download log results in either `TXT` or `JSON` format. This feature allows you to save log data for further analysis or to share it with others in a convenient and accessible format. ### Log result meta information -Above the received log lines you can find essential meta information, including: +The following meta information displays above the retrieved log lines: -- **Number of received logs**: Indicates the total count of logs received for the current query or time range. -- **Error**: Displays possible error in your log results -- **Common labels**: Shows common labels. -- **Total bytes processed**: Represents the cumulative size of the log data processed in bytes. +- **Number of received logs -** Indicates the total count of logs received for the current query or time range. +- **Error -** Displays any errors in your log results. +- **Common labels -** Displays common labels. +- **Total bytes processed -** Represents the cumulative size of the log data processed in bytes. -> **Note:** The availability of certain meta information may depend on the data source, and as a result, you may only see some of these details for specific data sources. +{{< admonition type="note" >}} +The availability of certain metadata may vary depending on the data source, so you might only see details related to those specific data sources. +{{< /admonition >}} ### Escaping newlines -Explore automatically detects some incorrectly escaped sequences in log lines, such as newlines (`\n`, `\r`) or tabs (`\t`). When it detects such sequences, Explore provides an "Escape newlines" option. +Explore automatically detects some incorrectly escaped sequences in log lines, such as newlines (`\n`, `\r`) or tabs (`\t`). When it detects such sequences, Explore provides an **Escape newlines** option. To automatically fix incorrectly escaped sequences that Explore has detected: -1. Click "Escape newlines" to replace the sequences. -2. Manually review the replacements to confirm their correctness. +1. Click **Escape newlines** to replace the sequences. +2. Review returned log lines. -Explore replaces these sequences. When it does so, the option will change from "Escape newlines" to "Remove escaping". Evaluate the changes as the parsing may not be accurate based on the input received. You can revert the replacements by clicking "Remove escaping". +Explore replaces these sequences, changing the option from **Escape newlines** to **Remove escaping**. Assess the changes, as the parsing may not be accurate based on the input. To revert the replacements, click **Remove escaping**. ### Log level -For the logs where a `level` label is specified, we use the value of this label to determine the log level and update color of each log line accordingly. If the log doesn't have specified level label, we try to find out if its content matches any of the supported expressions (see below for more information). The log level is always determined by the first match. In the case where Grafana is not able to infer a log level field, it will be visualized with an unknown log level. +For logs where a `level` label is specified, the value of this label is used to determine the log level and update the color of each log line accordingly. +If the log doesn't have a specified level label, Grafana attempts to determine if its content matches any of the supported expressions. +Refer to the following table for more information. The log level is always determined by the first match. If Grafana isn't able to infer a log level field, it gets visualized as an unknown log level. -> **Tip:** If you use a Loki data source and the "level" is part of your log line, you can use parsers (JSON, logfmt, regex,..) to extract the level information into a level label that is used to determine the level value. This will allow the histogram to show the various log levels as separate bars. +{{< admonition type="tip" >}} +When using the Loki data source, if `level` is part of your log line, you can use parsers such as `json`, `logfmt`, or `regex` to extract the level information into a level label. This label is used to determine the level value, allowing the histogram to display the various log levels as separate bars. +{{< /admonition >}} -**Supported log levels and mapping of log level abbreviation and expressions:** +**Log levels supported and mapping of log level abbreviation and expressions:** | Log level | Color | Supported expressions | | :-------- | :--------- | ---------------------------------------------- | @@ -104,66 +112,76 @@ For the logs where a `level` label is specified, we use the value of this label ### Highlight searched words -When your query includes specific words or expressions to search for, Explore will highlight these in the log lines for better visibility. This highlighting feature makes it easier to identify and focus on the relevant content in your logs. +When your query includes specific words or expressions for keyword search, Explore highlights them in log lines to enhance visibility. This highlighting feature facilitates easier identification and focus on the relevant content within your logs. -> **Note:** The ability to highlight search words may vary depending on the data source. For some data sources, the highlighting of search words may not be available. +{{< admonition type="note" >}} +The ability to highlight search words varies depending on data source. For some data sources, the highlighting of search words may not be available. +{{< /admonition >}} ### Log details view -In Explore, each log line has an expandable section called **Log details** that can be opened by clicking on the log line. The Log details view provides additional information and exploration options in the form of **Fields** and **Links** attached to the log lines, enabling a more robust interaction and analysis. +In Explore, each log line has an expandable section called **Log details** that you open by clicking on the log line. The Log details view provides additional information and exploration options in the form of **Fields** and **Links** attached to the log lines, enabling a more robust interaction and analysis. #### Fields -Within the Log details view, you have the ability to filter displayed fields in two ways: a positive filter (to focus on an specific field) and a negative filter (to exclude certain fields). These filters will update the corresponding query that produced the log line, adding equality and inequality expressions accordingly. If the data source has support, as it's the case for Loki and Elasticsearch, log details will check if the field is already present in the current query showing and active state (for positive filters only), allowing you to toggle it off the query, or changing the filter expression from positive to negative. +Within the **Log details** view, you have the ability to filter the displayed fields in two ways: a positive filter, which focuses on an specific field and a negative filter, which excludes certain fields. +These filters modify the corresponding query that generated the log line, incorporating equality and inequality expressions accordingly. -Additionally, you can select a subset of fields to visualize in the logs list instead of the complete log line by clicking on the eye icon. Finally, each field has a stats icon to display ad-hoc statistics in relation to all displayed logs. +If the data source supports it, as is the case with Loki and Elasticsearch, log details will verify whether the field is already included in the current query, indicating an active state for positive filters. This enables you to toggle it off from the query or convert the filter expression from positive to negative as necessary. + +Click the **eye icon** to select a subset of fields to visualize in the logs list instead of the complete log line. + +Each field has a **stats icon**, which displays ad-hoc statistics in relation to all displayed logs. #### Links -Grafana offers the functionality of data links or correlations, enabling you to convert any part of a log message into an internal or external link. These links can be used to navigate to related data or external resources, providing a seamless and convenient way to explore further information. +Grafana provides data links or correlations, allowing you to convert any part of a log message into an internal or external link. These links enable you to navigate to related data or external resources, offering a seamless and convenient way to explore additional information. + {{< figure src="/static/img/docs/explore/data-link-9-4.png" max-width="800px" caption="Data link in Explore" >}} ### Log context -Log context is a feature that allows you to display additional lines of context surrounding a log entry that matches a particular search query. This can be helpful in understanding the log entry's context, and is similar to the `-C` parameter in the `grep` command. +Log context is a feature that displays additional lines of context surrounding a log entry that matches a specific search query. This helps in understanding the context of the log entry and is similar to the `-C` parameter in the `grep` command. -You may encounter long lines of text that make it difficult to read and analyze the context around each log entry. This is where the **Wrap lines** toggle can come in handy. By enabling this toggle, Grafana will automatically wrap long lines of text so that they fit within the visible width of the viewer. This can make it easier to read and understand the log entries. +Toggle **Wrap lines** if you encounter long lines of text that make it difficult to read and analyze the context around log entries. By enabling this toggle, Grafana automatically wraps long lines of text to fit within the visible width of the viewer, making the log entries easier to read and understand. -The **Open in split view** button allows you to execute the context query for a log entry in a split screen in the Explore view. Clicking this button will open a new Explore pane with the context query displayed alongside the log entry, making it easier to analyze and understand the surrounding context. +Click **Open in split view** to execute the context query for a log entry in a split screen in the Explore view. Clicking this button opens a new Explore pane with the context query displayed alongside the log entry, making it easier to analyze and understand the surrounding context. -The log context query can also be opened in a new browser tab by pressing the Cmd/Ctrl button while clicking on the button to open the context modal. When opened in a new tab, the previously selected filters are applied as well. +Use Command-click or Ctrl+click to open the log context query in a new browser to view the context model. All previously selected filters get applied. ### Copy log line -You can easily copy the content of a selected log line to your clipboard by clicking on the `Copy log line` button. +Click **Copy log line** to copy the content of a selected log line to the clipboard. ### Copy link to log line -Linking of log lines in Grafana allows you to quickly navigate to specific log entries for precise analysis. By clicking the **Copy shortlink** button for a log line, you can generate and copy a [short URL]({{< relref "../developers/http_api/short_url/" >}}) that provides direct access to the exact log entry within an absolute time range. When you open the link, Grafana will automatically scroll to the corresponding log line and highlight it with a blue background, making it easy to identify and focus on the relevant information. +Linking log lines in Grafana allows you to quickly navigate to specific log entries for detailed and precise analysis. Click **Copy shortlink** to generate and copy a [short URL](/docs/grafana//developers/http_api/short_url/) that provides direct access to the exact log entry within an absolute time range. When you open the link, Grafana automatically scrolls to the corresponding log line and highlights it in blue, making it easy to identify and focus on relevant information. -> **Note:** This is currently only supported in Loki and other data sources that provide an `id` field. +{{< admonition type="note" >}} +The short URL feature is currently only supported in Loki and other data sources that provide an `id` field. +{{< /admonition >}} ## Live tailing -To view real-time logs from supported data sources, you can leverage the Live tailing feature in Explore. +Use the **Live tail** feature to view real-time logs from data sources. -1. Click the **Live** button in the Explore toolbar to switch to Live tail view. -2. While in Live tail view, new logs will appear from the bottom of the screen, and they will have a fading contrasting background, allowing you to easily track what's new. -3. If you wish to pause the Live tailing and explore previous logs without any interruptions, you can do so by clicking the **Pause** button or simply scrolling through the logs view. -4. To clear the view and remove all logs from the display, click on the **Clear logs** button. This action will reset the log view and provide you with a clean slate to continue your log analysis. -5. To resume Live tailing and continue viewing real-time logs, click the **Resume** button. -6. If you want to exit Live tailing and return to the standard Explore view, click the **Stop** button. +1. Click **Live** in the Explore toolbar to switch to Live tail view. +1. In **Live tail view**, new logs appear at the bottom of the screen, and have a contrasting background, allowing you to easily track what's new. +1. Click **Pause** to pause live tailing and explore previous logs without interruptions. or simply scroll through the logs view. +1. Click **Clear logs** to remove all displayed logs. This action resets the log view and provides a clean slate to continue your log analysis +1. Click **Resume** to resume live tailing and continue viewing real-time logs. +1. Click **Stop** to exit live tailing and return to the standard Explore view. -Using the Live tailing feature, you can keep a close eye on the latest logs as they come in, making it easier to monitor real-time events and detect issues promptly. +The **Live tailing feature** allows you to monitor the latest logs in real-time, making it easier to track events as they occur and promptly detect issues. {{< video-embed src="/static/img/docs/v95/explore_live_tailing.mp4" >}} ### Logs sample -If the selected data source implements logs sample, and supports both log and metric queries, then for metric queries you will be able to automatically see samples of log lines that contributed to visualized metrics. This feature is currently supported by Loki data sources. +If the selected data source supports log samples and both log and metric queries, you will automatically see log line samples that contribute to the visualized metrics for metric queries. **This feature is currently only supported by the Loki data source.** ### Switch from metrics to logs -If you are coming from a metrics data source that implements `DataSourceWithQueryExportSupport` (such as Prometheus) to a logging data source that supports `DataSourceWithQueryImportSupport` (such as Loki), then it will keep the labels from your query that exist in the logs and use those to query the log streams. +If you are transitioning from a metrics data source that implements `DataSourceWithQueryExportSupport` (such as Prometheus) to a logging data source that supports `DataSourceWithQueryImportSupport` (such as Loki), Explore retains the labels from your query that exist in the logs and use them to query the log streams. -For example, the following Prometheus query `grafana_alerting_active_alerts{job="grafana"}` after switching to the Loki data source, will change to `{job="grafana"}`. This will return a chunk of logs in the selected time range that can be grepped/text searched. +For example, after switching to the Loki data source, the Prometheus query `grafana_alerting_active_alerts{job="grafana"}` changes to `{job="grafana"}`. This will retrieve a set of logs within the specified time range, which can be searched using grep or text search. diff --git a/docs/sources/explore/trace-integration.md b/docs/sources/explore/trace-integration.md index fbf2032429171..da14c571cbc6a 100644 --- a/docs/sources/explore/trace-integration.md +++ b/docs/sources/explore/trace-integration.md @@ -1,5 +1,4 @@ --- -description: Tracing in Explore keywords: - explore - trace @@ -8,167 +7,161 @@ labels: - cloud - enterprise - oss -title: Tracing in Explore +title: Traces in Explore weight: 20 --- -# Tracing in Explore +# Traces in Explore -You can use Explore to query and visualize traces from tracing data sources. +You can use Explore to query and visualize traces from tracing data sources. Supported data sources include: -Supported data sources are: - -- [Tempo]({{< relref "../datasources/tempo/" >}}) (supported ingestion formats: OpenTelemetry, Jaeger, and Zipkin) -- [Jaeger]({{< relref "../datasources/jaeger/" >}}) -- [Zipkin]({{< relref "../datasources/zipkin/" >}}) +- [Tempo](/docs/grafana//datasources/tempo/) +- [Jaeger](/docs/grafana//datasources/jaeger/) +- [Zipkin](/docs/grafana//datasources/zipkin/) - [X-Ray](https://grafana.com/grafana/plugins/grafana-x-ray-datasource) -- [Azure Monitor Application Insights]({{< relref "../datasources/azure-monitor/" >}}) +- [Azure Monitor](/docs/grafana/latest/datasources/azure-monitor/) - [ClickHouse](https://github.com/grafana/clickhouse-datasource) -- [New Relic](https://grafana.com/grafana/plugins/grafana-newrelic-datasource) -- [Infinity](https://grafana.com/grafana/plugins/yesoreyeram-infinity-datasource) - -For information on how to configure queries for the data sources listed above, refer to the documentation for specific data source. +- [New Relic](/docs/plugins/grafana-newrelic-datasource/latest/) +- [Infinity](/docs/plugins/yesoreyeram-infinity-datasource/latest/) -## Query editor +Here are some references to learn more about traces and how you can use them: -You can query and search tracing data using a data source's query editor. +- [Introduction to tracing](https://grafana.com/docs/tempo//introduction/) +- [Trace structure](https://grafana.com/docs/tempo//traceql/trace-structure/#trace-structure) +- [Traces and telemetry](https://grafana.com/docs/tempo//introduction/telemetry/) +- [Using traces to find solutions to problems](https://grafana.com/docs/tempo//introduction/solutions-with-traces/) +- [Best practices for tracing](/docs/grafana//datasources/tempo/tracing-best-practices/) -Each data source can have it's own query editor. The query editor for the Tempo data source is slightly different than the query editor for the Jaeger data source. +## Query editors -For information on querying each data source, refer to their documentation: +You can query and search tracing data using a data source's query editor. Note that data sources in Grafana have unique query editors. -- [Tempo query editor]({{< relref "../datasources/tempo/query-editor" >}}) -- [Jaeger query editor]({{< relref "../datasources/jaeger/#query-the-data-source" >}}) -- [Zipkin query editor]({{< relref "../datasources/zipkin/#query-the-data-source" >}}) -- [Azure Monitor Application Insights query editor]({{< relref "../datasources/azure-monitor/query-editor/#query-application-insights-traces" >}}) -- [ClickHouse query editor](https://clickhouse.com/docs/en/integrations/grafana/query-builder#traces) +For information on how to use the query editor to create queries for tracing data sources, refer to the documentation for each individual data source. ## Trace view -This section explains the elements of the Trace View. +Grafana's trace view provides an overview of a request as it travels through your system. The following sections provide detail on various elements of the trace view. -{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the trace view" >}} +{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view.png" class="docs-image--no-shadow" max-width= "900px" caption="Trace view" >}} ### Header -{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view-header.png" class="docs-image--no-shadow" max-width= "750px" caption="Screenshot of the trace view header" >}} +The trace view header includes the following: -- Header title: Shows the name of the root span and trace ID. -- Search: Highlights spans containing the searched text. -- Metadata: Various metadata about the trace. +- **Header title** - Shows the name of the root span and trace ID. +- **Search** - Highlights spans containing the searched text. +- **Metadata** - Various metadata about the trace. + +{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view-header.png" class="docs-image--no-shadow" max-width= "750px" caption="Trace view header" >}} ### Minimap -{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view-minimap.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the trace view minimap" >}} +**Minimap** displays a condensed view of the trace timeline. Drag your mouse over the minimap to zoom into a smaller time range. This also updates the main timeline, making it easier to view shorter spans +When zoomed in, hovering over the minimap displays **Reset selection**, which resets the zoom. -Shows condensed view or the trace timeline. Drag your mouse over the minimap to zoom into smaller time range. Zooming will also update the main timeline, so it is easy to see shorter spans. Hovering over the minimap, when zoomed, will show Reset Selection button which resets the zoom. +{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view-minimap.png" class="docs-image--no-shadow" max-width= "900px" caption="Trace view minimap example" >}} -### Span filters +### Timeline -![Screenshot of span filtering](/media/docs/tempo/screenshot-grafana-tempo-span-filters-v10-1.png) +Timeline shows list of spans within the trace. Each span row consists of the following components: -Using span filters, you can filter your spans in the trace timeline viewer. The more filters you add, the more specific are the filtered spans. +- **Expand children** - Expands or collapses all the children spans of the selected span. +- **Service name** - Name of the service logged the span. +- **Operation name** - Name of the operation that this span represents. +- **Span duration bar** - Visual representation of the operation duration within the trace. -You can add one or more of the following filters: +Click anywhere on the span row to reveal span details. -- Resource service name -- Span name -- Duration -- Tags (which include tags, process tags, and log fields) +{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view-timeline.png" class="docs-image--no-shadow" max-width= "900px" caption="Trace view timeline" >}} -To only show the spans you have matched, you can press the `Show matches only` toggle. +### Span details -{{< youtube id="VP2XV3IIc80" >}} +Traces are composed of one or more spans. +A span is a unit of work within a trace that has a start time relative to the beginning of the trace, a duration and an operation name for the unit of work. +It usually has a reference to a parent span, unless it’s the first span, the root span, in a trace. +It frequently includes key/value attributes that are relevant to the span itself, for example the HTTP method used in the request, as well as other metadata such as the service name, sub-span events, or links to other spans. -### Timeline +You can expand any span in a trace and view the details, including the span and resource attributes. -{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view-timeline.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the trace view timeline" >}} +For more information about spans and traces, refer to [Introduction to tracing](https://grafana.com/docs/tempo/latest/introduction/) in the Tempo documentation. -Shows list of spans within the trace. Each span row consists of these components: +Span details include: -- Expand children button: Expands or collapses all the children spans of selected span. -- Service name: Name of the service logged the span. -- Operation name: Name of the operation that this span represents. -- Span duration bar: Visual representation of the operation duration within the trace. +- **Span attributes** - Key/value pairs that provides context for spans. For example, if the span deals with calling another service via HTTP, an attribute could include the HTTP URL (maybe as the span attribute key `http.url`) and the HTTP status code returned (as the span attribute `http.status_code`). -Clicking anywhere on the span row shows span details. +- **Resource attributes** - Key/value pairs that describe the context of how the span was collected. -### Span details +Refer to [Span and resource attributes](/docs/tempo//operations/best-practices/#span-and-resource-attributes) for more detail. -{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view-span-details.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the trace view span details" >}} +{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view-span-details.png" class="docs-image--no-shadow" max-width= "900px" caption="Trace view span details" >}} -- Operation name. -- Span metadata. -- Tags: Any tags associated with this span. -- Process metadata: Metadata about the process that logged this span. -- Logs: List of logs logged by this span and associated key values. In case of Zipkin logs section shows Zipkin annotations. +### Span filters -### Trace to logs +Span filters allow you to refine the spans displayed in the trace timeline viewer. +The more filters you add, the more specific the filtered spans become. +Click on a trace to access Span filters. -You can navigate from a span in a trace view directly to logs relevant for that span. This feature is available for Tempo, Jaeger, and Zipkin data sources. Refer to their [relevant documentation](/docs/grafana/latest/datasources/tempo/#trace-to-logs) for configuration instructions. +![Screenshot of span filtering](/media/docs/tempo/screenshot-grafana-tempo-span-filters-v10-1.png) -{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view-trace-to-logs.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the trace view in Explore with icon next to the spans" >}} +You can add one or more of the following filters: -Click the document icon to open a split view in Explore with the configured data source and query relevant logs for the span. +- **Service name** - Filter by selecting a service name from the dropdown. +- **Span name** - Filter by selecting a span name from the dropdown. +- **Duration** - Filter by duration. Accepted units include ns, us, ms, s, m, h. +- **Tags** - Filter by tags, process tags, or log fields in your span. -### Trace to metrics +To only show the spans you have matched, toggle **Show matches only**. -{{% admonition type="note" %}} -This feature is currently in beta and behind the `traceToMetrics` feature toggle. -{{% /admonition %}} +Refer to [Span filters](/docs/grafana//datasources/tempo/span-filters/) for more in depth information. -You can navigate from a span in a trace view directly to metrics relevant for that span. This feature is available for Tempo, Jaeger, and Zipkin data sources. Refer to their [relevant documentation](/docs/grafana/latest/datasources/tempo/configure-tempo-data-source/#trace-to-metrics) for configuration instructions. +Watch the following video to learn more about filtering trace spans in Grafana: +{{< youtube id="VP2XV3IIc80" >}} -### Trace to profiles +### Trace to logs -Using Trace to profiles, you can use Grafana’s ability to correlate different signals by adding the functionality to link between traces and profiles. -Refer to the [relevant documentation](/docs/grafana/latest/datasources/tempo/configure-tempo-data-source#trace-to-profiles) for configuration instructions. +You can navigate from a span in a trace view directly to logs relevant for that span. +This feature is available for the Tempo, Jaeger, and Zipkin data sources. +Refer to each individual data source's documentation for configuration instructions. -{{< figure src="/static/img/docs/tempo/profiles/tempo-trace-to-profile.png" max-width="900px" class="docs-image--no-shadow" alt="Selecting a link in the span queries the profile data source" >}} +Click the document icon to open a split view in Explore with the configured data source and query relevant logs for the span. -## Node graph +{{< figure src="/media/docs/tempo/screenshot-grafana-trace-view-trace-to-logs.png" class="docs-image--no-shadow" max-width= "900px" caption="Trace to logs" >}} -You can optionally expand the node graph for the displayed trace. Depending on the data source, this can show spans of the trace as nodes in the graph, or as some additional context like service graph based on the current trace. +### Trace to metrics + +You can navigate from a span in a trace view directly to metrics relevant for that span. +This feature is available for the Tempo, Jaeger, and Zipkin data sources. -{{< figure src="/media/docs/tempo/screenshot-grafana-node-graph.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the node graph" >}} +Refer to each individual data source's documentation for configuration instructions. +For Tempo, refer to [Trace to metrics configuration](https://grafana.com/docs/grafana//datasources/tempo/configure-tempo-data-source/#trace-to-metrics). -## Service Graph +### Trace to profiles -The Service Graph visualizes the span metrics (traces data for rates, error rates, and durations (RED)) and service graphs. -Once the requirements are set up, this pre-configured view is immediately available. +Using Trace to profiles, you can use Grafana’s ability to correlate different signals by adding the functionality to link between traces and profiles. -For more information, refer to the [Service Graph view section]({{< relref "../datasources/tempo/#open-the-service-graph-view" >}}) of the Tempo data source page and the [service graph view page](/docs/tempo/latest/metrics-generator/service-graph-view/) in the Tempo documentation. +For Tempo refer to [Trace to profiles](/docs/grafana//datasources/tempo/configure-tempo-data-source#trace-to-profiles) for configuration instructions. -{{< figure src="/static/img/docs/grafana-cloud/apm-overview.png" class="docs-image--no-shadow" max-width= "900px" caption="Screenshot of the Service Graph view" >}} +{{< figure src="/static/img/docs/tempo/profiles/tempo-trace-to-profile.png" max-width="900px" class="docs-image--no-shadow" alt="Selecting a link in the span queries the profile data source" >}} + +## Node graph -## Data API +You can also expand the node graph for a displayed trace. If the data source supports it, this displays spans of the trace as nodes in the graph, or provides additional context, such as a service graph based on the current trace. -This visualization needs a specific shape of the data to be returned from the data source in order to correctly display it. +Refer to [Node graph](/docs/grafana//panels-visualizations/visualizations/node-graph/) for additional information. -Data source needs to return data frame and set `frame.meta.preferredVisualisationType = 'trace'`. +{{< admonition type="note" >}} +The node graph requires data to be returned from the data source in a specific format to display correctly. Refer to [Data API](/docs/grafana//panels-visualizations/visualizations/node-graph/#data-api), [Nodes data frame structure](/docs/grafana/latest/panels-visualizations/visualizations/node-graph/#nodes-data-frame-structure) and [Node graph data requirements](/docs/grafana/latest/panels-visualizations/visualizations/node-graph/#data-requirements) for additional information and configuration instructions. +{{< /admonition >}} -### Data frame structure +{{< figure src="/media/docs/tempo/screenshot-grafana-node-graph.png" class="docs-image--no-shadow" max-width= "900px" caption="Node graph" >}} -Required fields: +## Service graph -| Field name | Type | Description | -| ------------ | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -| traceID | string | Identifier for the entire trace. There should be only one trace in the data frame. | -| spanID | string | Identifier for the current span. SpanIDs should be unique per trace. | -| parentSpanID | string | SpanID of the parent span to create child parent relationship in the trace view. Can be `undefined` for root span without a parent. | -| serviceName | string | Name of the service this span is part of. | -| serviceTags | TraceKeyValuePair[] | List of tags relevant for the service. | -| startTime | number | Start time of the span in millisecond epoch time. | -| duration | number | Duration of the span in milliseconds. | +A service graph visualizes span metrics, including rates, error rates, and durations (RED), along with service relationships. Once the requirements are configured, this pre-configured view is immediately available. -Optional fields: +For additional information refer to the following documentation: -| Field name | Type | Description | -| -------------- | ------------------- | ------------------------------------------------------------------ | -| logs | TraceLog[] | List of logs associated with the current span. | -| tags | TraceKeyValuePair[] | List of tags associated with the current span. | -| warnings | string[] | List of warnings associated with the current span. | -| stackTraces | string[] | List of stack traces associated with the current span. | -| errorIconColor | string | Color of the error icon in case span is tagged with `error: true`. | +- [Service Graph and Service Graph view](/docs/grafana//datasources/tempo/service-graph/) +- [Service graph view](/docs/tempo//metrics-generator/service-graph-view/) in Tempo documentation -For details about the types see [TraceSpanRow](https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/types/trace.ts#L28), [TraceKeyValuePair](https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/types/trace.ts#L4) and [TraceLog](https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/types/trace.ts#L12). +{{< figure src="/static/img/docs/grafana-cloud/apm-overview.png" class="docs-image--no-shadow" max-width= "900px" caption="Service graph view" >}} diff --git a/docs/sources/panels-visualizations/panel-editor-overview/index.md b/docs/sources/panels-visualizations/panel-editor-overview/index.md index 38fba108702f0..62175bb9cd9f6 100644 --- a/docs/sources/panels-visualizations/panel-editor-overview/index.md +++ b/docs/sources/panels-visualizations/panel-editor-overview/index.md @@ -2,7 +2,6 @@ aliases: - ../dashboards/add-organize-panels/ - ../dashboards/dashboard-create/ - - ../features/dashboard/dashboards/ - ../panels/add-panels-dynamically/about-repeating-panels-rows/ - ../panels/add-panels-dynamically/configure-repeating-panels/ - ../panels/add-panels-dynamically/configure-repeating-rows/ diff --git a/docs/sources/panels-visualizations/visualizations/geomap/index.md b/docs/sources/panels-visualizations/visualizations/geomap/index.md index c79d518988232..d64d6bda9697d 100644 --- a/docs/sources/panels-visualizations/visualizations/geomap/index.md +++ b/docs/sources/panels-visualizations/visualizations/geomap/index.md @@ -35,7 +35,7 @@ labels: title: Geomap weight: 100 refs: - data-format-supported-by-the-node-graph-visualization: + data-format: - pattern: /docs/grafana/ destination: /docs/grafana//panels-visualizations/visualizations/node-graph/#data-api - pattern: /docs/grafana-cloud/ @@ -270,8 +270,9 @@ The markers layer allows you to display data points as different marker shapes s ![Markers Layer](/static/img/docs/geomap-panel/geomap-markers-8-1-0.png) -![Markers Layer Options](/static/img/docs/geomap-panel/geomap-markers-options-8-1-0.png) +{{< figure src="/media/docs/grafana/panels-visualizations/geomap-markers-options-11-1-0.png" max-width="350px" alt="Markers layer options" >}} +- **Data** and **Location mode** configure the data settings for the layer. For more information, refer to [Data](#data) and [Location mode](#location-mode). - **Size** configures the size of the markers. The default is `Fixed size`, which makes all marker sizes the same regardless of the data; however, there is also an option to size the markers based on data corresponding to a selected field. `Min` and `Max` marker sizes have to be set such that the markers can scale within this range. - **Symbol** allows you to choose the symbol, icon, or graphic to aid in providing additional visual context to your data. Choose from assets that are included with Grafana such as simple symbols or the Unicon library. You can also specify a URL containing an image asset. The image must be a scalable vector graphic (SVG). - **Symbol Vertical Align** configures the vertical alignment of the symbol relative to the data point. Note that the symbol's rotation angle is applied first around the data point, then the vertical alignment is applied relative to the rotation of the symbol. @@ -294,8 +295,9 @@ Similar to `Markers`, you are prompted with various options to determine which d ![Heatmap Layer](/static/img/docs/geomap-panel/geomap-heatmap-8-1-0.png) -![Heatmap Layer Options](/static/img/docs/geomap-panel/geomap-heatmap-options-8-1-0.png) +{{< figure src="/media/docs/grafana/panels-visualizations/geomap-heatmap-options-11-1-0.png" max-width="350px" alt="Heatmap layer options" >}} +- **Data** and **Location mode** configure the data settings for the layer. For more information, refer to [Data](#data) and [Location mode](#location-mode). - **Weight values** configure the intensity of the heatmap clusters. `Fixed value` keeps a constant weight value throughout all data points. This value should be in the range of 0~1. Similar to Markers, there is an alternate option in the drop-down to automatically scale the weight values depending on data values. - **Radius** configures the size of the heatmap clusters. - **Blur** configures the amount of blur on each cluster. @@ -345,6 +347,7 @@ The Night / Day layer displays night and day regions based on the current time r ### Options +- **Data** configures the data set for the layer. For more information, refer to [Data](#data). - **Show** toggles the time source from panel time range. - **Night region color** picks the color for the night region. - **Display sun** toggles the sun icon. @@ -369,6 +372,7 @@ The Route layer renders data points as a route. ### Options +- **Data** and **Location mode** configure the data settings for the layer. For more information, refer to [Data](#data) and [Location mode](#location-mode). - **Size** sets the route thickness. Fixed value by default. When field data is selected you can set the Min and Max range in which field data can scale. - **Color** sets the route color. Set to `Fixed color` by default. You can also tie the color to field data. - **Fill opacity** configures the opacity of the route. @@ -397,6 +401,7 @@ The Photos layer renders a photo at each data point. ### Options +- **Data** and **Location mode** configure the data settings for the layer. For more information, refer to [Data](#data) and [Location mode](#location-mode). - **Image Source field** allows you to select a string field containing image data in either of the following formats: - **Image URLs** - **Base64 encoded** - Image binary ("data:image/png;base64,...") @@ -424,13 +429,14 @@ The Photos layer renders a photo at each data point. The Network layer is currently in [public preview](/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available. {{% /admonition %}} -The Network layer renders a network graph. This layer supports the same [data format supported by the node graph visualization](ref:data-format-supported-by-the-node-graph-visualization) with the addition of [geospatial data]({{< relref "#location">}}) included in the nodes data. The geospatial data is used to locate and render the nodes on the map. +The Network layer renders a network graph. This layer supports the same [data format supported by the node graph visualization](ref:data-format) with the addition of [geospatial data](#location-mode) included in the nodes data. The geospatial data is used to locate and render the nodes on the map. {{< figure src="/media/docs/grafana/screenshot-grafana-10-1-geomap-network-layer-v2.png" max-width="750px" caption="Geomap network layer" >}} {{< video-embed src="/media/docs/grafana/screen-recording-10-1-geomap-network-layer-from-node-graph.mp4" max-width="750px" caption="Node graph to Geomap network layer" >}} ### Options +- **Data** and **Location mode** configure the data settings for the layer. For more information, refer to [Data](#data) and [Location mode](#location-mode). - **Arrow** sets the arrow direction to display for each edge, with forward meaning source to target. Choose from: - **None** - **Forward** diff --git a/docs/sources/panels-visualizations/visualizations/node-graph/index.md b/docs/sources/panels-visualizations/visualizations/node-graph/index.md index eba0095218911..eabc6d2e60b66 100644 --- a/docs/sources/panels-visualizations/visualizations/node-graph/index.md +++ b/docs/sources/panels-visualizations/visualizations/node-graph/index.md @@ -25,12 +25,37 @@ Node graphs can visualize directed graphs or networks. They use a directed force ![Node graph visualization](/static/img/docs/node-graph/node-graph-8-0.png 'Node graph') +## Configure a node graph visualization + The following video provides beginner steps for creating node panel visualizations. You'll learn the data requirements and caveats, special customizations, and much more: {{< youtube id="VrvsMkRwoKw" >}} {{< docs/play title="Node graph panel" url="https://play.grafana.org/d/bdodfbi3d57uoe/" >}} +## Panel options + +{{< docs/shared lookup="visualizations/panel-options.md" source="grafana" version="" >}} + +## Nodes options + +The **Nodes** options section provides configurations for node behaviors. + +- **Main stat unit** - Choose which unit the main stat displays in the graph's nodes. +- **Secondary stat unit** - Choose which unit the secondary stat displays in the graph's nodes. +- **Arc sections** - Configure which fields define the size of the colored circle around the node and select a color for each. You can add multiple fields. + +{{< admonition type="note" >}} +Defining arc sections overrides the automatic detection of `arc__*` and `color` fields described in the **Optional fields** section of [Nodes data frame structure](#nodes-data-frame-structure). +{{< /admonition >}} + +## Edges options + +The **Edges** options section provides configurations for node edges behaviors. + +- **Main stat unit** - Choose which unit the main stat displays in the graph's edges. +- **Secondary stat unit** - Choose which unit the secondary stat displays in the graph's edges. + ## Data requirements A node graph requires a specific shape of the data to be able to display its nodes and edges. This means not every data source or query can be visualized with this graph. If you want to use this as a data source developer see the section about data API. @@ -148,7 +173,3 @@ Optional fields: | icon | string | Name of the icon to show inside the node instead of the default stats. Only Grafana built in icons are allowed (see the available icons [here](https://developers.grafana.com/ui/latest/index.html?path=/story/docs-overview-icon--icons-overview)). | | nodeRadius | number | Radius value in pixels. Used to manage node size. | | highlighted | boolean | Sets whether the node should be highlighted. Useful for example to represent a specific path in the graph by highlighting several nodes and edges. Default: `false` | - -## Panel options - -{{< docs/shared lookup="visualizations/panel-options.md" source="grafana" version="" >}} diff --git a/docs/sources/panels-visualizations/visualizations/pie-chart/index.md b/docs/sources/panels-visualizations/visualizations/pie-chart/index.md index db892481358ba..01f49e3de1aca 100644 --- a/docs/sources/panels-visualizations/visualizations/pie-chart/index.md +++ b/docs/sources/panels-visualizations/visualizations/pie-chart/index.md @@ -27,6 +27,12 @@ refs: Pie charts display reduced series, or values in a series, from one or more queries, as they relate to each other, in the form of slices of a pie. The arc length, area and central angle of a slice are all proportional to the slices value, as it relates to the sum of all values. This type of chart is best used when you want a quick comparison of a small set of values in an aesthetically pleasing form. +## Configure a pie chart visualization + +The following video guides you through the creation steps and common customizations of pie chart visualizations and is great for beginners: + +{{< youtube id="A_lDhM9w4_g" >}} + {{< docs/play title="Grafana Bar Charts and Pie Charts" url="https://play.grafana.org/d/ktMs4D6Mk/" >}} ## Panel options diff --git a/docs/sources/panels-visualizations/visualizations/time-series/index.md b/docs/sources/panels-visualizations/visualizations/time-series/index.md index 00aa41bb1d798..5a1907da8d2a1 100644 --- a/docs/sources/panels-visualizations/visualizations/time-series/index.md +++ b/docs/sources/panels-visualizations/visualizations/time-series/index.md @@ -59,21 +59,26 @@ refs: destination: /docs/grafana//alerting/alerting-rules/create-grafana-managed-rule/ - pattern: /docs/grafana-cloud/ destination: /docs/grafana-cloud/alerting-and-irm/alerting/alerting-rules/create-grafana-managed-rule/ + panel-editor-alerts: + - pattern: /docs/grafana/ + destination: /docs/grafana//panels-visualizations/panel-editor-overview/#data-section + - pattern: /docs/grafana-cloud/ + destination: /docs/grafana-cloud/visualizations/panels-visualizations/panel-editor-overview/#data-section --- # Time series -Time series visualizations are the default and primary way to visualize data points over intervals of time as a graph. They can render series as lines, points, or bars. They're versatile enough to display almost any time-series data. +Time series visualizations are the default way to visualize data points over intervals of time, as a graph. They can render series as lines, points, or bars and are versatile enough to display almost any time-series data. {{< figure src="/static/img/docs/time-series-panel/time_series_small_example.png" max-width="1200px" alt="Time series" >}} {{< admonition type="note" >}} -You can migrate from the old Graph visualization to the new time series visualization. To migrate, open the panel and click the **Migrate** button in the side pane. +You can migrate from the legacy Graph visualization to the time series visualization. To migrate, open the panel and click the **Migrate** button in the side pane. {{< /admonition >}} ## Configure a time series visualization -The following video guides you through the creation steps and common customizations of time series visualizations and is great for beginners: +The following video guides you through the creation steps and common customizations of time series visualizations, and is great for beginners: {{< youtube id="RKtW87cPxsw" >}} @@ -81,40 +86,37 @@ The following video guides you through the creation steps and common customizati ## Supported data formats -Time series visualizations require time series data; that is a sequence of measurements, ordered in time, where every row in the table represents one individual measurement at a specific time. Learn more about [time series data](https://grafana.com/docs/grafana//fundamentals/timeseries/). +Time series visualizations require time-series data—a sequence of measurements, ordered in time, and formatted as a table—where every row in the table represents one individual measurement at a specific time. Learn more about [time-series data](https://grafana.com/docs/grafana//fundamentals/timeseries/). ## Alert rules -You can [link alert rules](ref:link-alert) to time series visualizations to observe when alerts fire and are resolved in the form of annotations. In addition, you can create alert rules from the **Alert** tab within the panel editor. - -## Transform override property +You can [link alert rules](ref:link-alert) to time series visualizations in the form of annotations to observe when alerts fire and are resolved. In addition, you can create alert rules from the **Alert** tab within the [panel editor](ref:panel-editor-alerts). -Use the **Transform** override property to transform series values without affecting the values shown in the tooltip, context menu, or legend. +## Special overrides - +The following overrides help you further refine a time series visualization. -- **Negative Y transform:** Flip the results to negative values on the Y axis. -- **Constant:** Show the first value as a constant line. +### Transform override property -{{< docs/shared lookup="visualizations/multiple-y-axes.md" source="grafana" version="" leveloffset="+1" >}} +Use the **Graph styles > Transform** [override property](#field-overrides) to transform series values without affecting the values shown in the tooltip, context menu, or legend. Choose from the following transform options: - +- **Constant** - Show the first value as a constant line. +- **Negative Y transform** - Flip the results to negative values on the y-axis. -## Add the Fill below to override +### Fill below to override property -The **Fill below to** option fills the area between two series. This option is only available as a series/field override. - -1. Edit the panel and click **Overrides**. -1. Select the fields to fill below. -1. In **Add override property**, select **Fill below to**. -1. Select the series for which you want the fill to stop. +The **Graph styles > Fill below to** [override property](#field-overrides) fills the area between two series. When you configure the property, select the series for which you want the fill to stop. The following example shows three series: Min, Max, and Value. The Min and Max series have **Line width** set to 0. Max has a **Fill below to** override set to Min, which fills the area between Max and Min with the Max line color. {{< figure src="/static/img/docs/time-series-panel/fill-below-to-7-4.png" max-width="600px" alt="Fill below to example" >}} +{{< docs/shared lookup="visualizations/multiple-y-axes.md" source="grafana" version="" leveloffset="+2" >}} + ## Configuration options +{{< docs/shared lookup="visualizations/config-options-intro.md" source="grafana" version="" >}} + ### Panel options {{< docs/shared lookup="visualizations/panel-options.md" source="grafana" version="" >}} @@ -129,30 +131,30 @@ The following example shows three series: Min, Max, and Value. The Min and Max s ### Axis options -Options under the axis category change how the x- and y-axes are rendered. Some options do not take effect until you click outside of the field option box you are editing. You can also or press `Enter`. - -| Option | Description | -| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Time zone | Set the desired time zone(s) to display along the x-axis. | -| [Placement](#placement) | Select the placement of the y-axis. | -| Label | Set a y-axis text label. If you have more than one y-axis, then you can assign different labels using an override. | -| Width | Set a fixed width of the axis. By default, Grafana dynamically calculates the width of an axis. By setting the width of the axis, data with different axes types can share the same display proportions. This setting makes it easier for you to compare more than one graph’s worth of data because the axes are not shifted or stretched within visual proximity to each other. | -| Show grid lines | Set the axis grid line visibility.
| -| Color | Set the color of the axis. | -| Show border | Set the axis border visibility. | -| Scale | Set the y-axis values scale.
| -| Centered zero | Set the y-axis to be centered on zero. | -| [Soft min](#soft-min-and-soft-max) | Set a soft min to better control the y-axis limits. zero. | -| [Soft max](#soft-min-and-soft-max) | Set a soft max to better control the y-axis limits. zero. | +Options under the **Axis** section control how the x- and y-axes are rendered. Some options don't take effect until you click outside of the field option box you're editing. You can also press `Enter`. + +| Option | Description | +| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Time zone | Set the desired time zones to display along the x-axis. | +| [Placement](#placement) | Select the placement of the y-axis. | +| Label | Set a y-axis text label. If you have more than one y-axis, then you can assign different labels using an override. | +| Width | Set a fixed width of the axis. By default, Grafana dynamically calculates the width of an axis. By setting the width of the axis, data with different axes types can share the same display proportions. This setting makes it easier for you to compare more than one graph’s worth of data because the axes aren't shifted or stretched within visual proximity to each other. | +| Show grid lines | Set the axis grid line visibility.
| +| Color | Set the color of the axis. | +| Show border | Set the axis border visibility. | +| Scale | Set the y-axis values scale.
| +| Centered zero | Set the y-axis so it's centered on zero. | +| [Soft min](#soft-min-and-soft-max) | Set a soft min to better control the y-axis limits. zero. | +| [Soft max](#soft-min-and-soft-max) | Set a soft max to better control the y-axis limits. zero. | #### Placement -Select the placement of the y-axis. +Select the placement of the y-axis. Choose from the following: -- **Auto:** Automatically assigns the y-axis to the series. When there are two or more series with different units, Grafana assigns the left axis to the first unit and the right axis to the units that follow. -- **Left:** Display all y-axes on the left side. -- **Right:** Display all y-axes on the right side. -- **Hidden:** Hide all axes. To selectively hide axes, [Add a field override](ref:add-a-field-override) that targets specific fields. +- **Auto** - Automatically assigns the y-axis to the series. When there are two or more series with different units, Grafana assigns the left axis to the first unit and the right axis to the units that follow. +- **Left** - Display all y-axes on the left side. +- **Right** - Display all y-axes on the right side. +- **Hidden** - Hide all axes. To selectively hide axes, [Add a field override](ref:add-a-field-override) that targets specific fields. #### Soft min and soft max @@ -166,71 +168,69 @@ To define hard limits of the y-axis, set standard min/max options. For more info ### Graph styles options +The options under the **Graph styles** section let you control the general appearance of the graph, excluding [color](#standard-options). + | Option | Description | | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Style](#style) | Use this option to define how to display your time series data. | -| [Line interpolation](#line-interpolation) | This option controls how the graph interpolates the series line. | -| [Line width](#line-width) | Line width is a slider that controls the thickness for series lines or the outline for bars. | -| [Fill opacity](#fill-opacity) | Use opacity to specify the series area fill color. | -| [Gradient mode](#gradient-mode) | Gradient mode specifies the gradient fill, which is based on the series color. | -| [Line style](#line-style) | Set the style of the line. | +| [Style](#style) | Choose whether to display your time-series data as lines, bars, or points. | +| [Line interpolation](#line-interpolation) | Choose how the graph interpolates the series line. | +| Line width | Set the thickness of the series lines or the outline for bars using the **Line width** slider. | +| [Fill opacity](#fill-opacity) | Set the series area fill color using the **Fill opacity** slider. | +| [Gradient mode](#gradient-mode) | Choose a gradient mode to control the gradient fill, which is based on the series color. | +| [Line style](#line-style) | Choose a solid, dashed, or dotted line style. | | [Connect null values](#connect-null-values) | Choose how null values, which are gaps in the data, appear on the graph. | | [Disconnect values](#disconnect-values) | Choose whether to set a threshold above which values in the data should be disconnected. | -| [Show points](#show-points) | You can configure your visualization to add points to lines or bars. | +| [Show points](#show-points) | Set whether to show data points to lines or bars. | | Point size | Set the size of the points, from 1 to 40 pixels in diameter. | -| [Stack series](#stack-series) | Stacking allows Grafana to display series on top of each other. | +| [Stack series](#stack-series) | Set whether Grafana displays series on top of each other. | | [Bar alignment](#bar-alignment) | Set the position of the bar relative to a data point. | | Bar width factor | Set the width of the bar relative to minimum space between data points. A factor of 0.5 means that the bars take up half of the available space between data points. A factor of 1.0 means that the bars take up all available space. | #### Style -Use this option to define how to display your time series data. You can use overrides to combine multiple styles in the same graph. - -- Lines -- Bars -- Points +Choose whether to display your time-series data as lines, bars, or points. You can use overrides to combine multiple styles in the same graph. Choose from the following: ![Style modes](/static/img/docs/time-series-panel/style-modes-v9.png) #### Line interpolation -This option controls how the graph interpolates the series line. +Choose how the graph interpolates the series line: -- **Linear:** Points are joined by straight lines. -- **Smooth:** Points are joined by curved lines that smooths transitions between points. -- **Step before:** The line is displayed as steps between points. Points are rendered at the end of the step. -- **Step after:** The line is displayed as steps between points. Points are rendered at the beginning of the step. +- **Linear** - Points are joined by straight lines. +- **Smooth** - Points are joined by curved lines that smooths transitions between points. +- **Step before** - The line is displayed as steps between points. Points are rendered at the end of the step. +- **Step after** - The line is displayed as steps between points. Points are rendered at the beginning of the step. #### Line width -Line width is a slider that controls the thickness for series lines or the outline for bars. +Set the thickness of the series lines or the outline for bars using the **Line width** slider. #### Fill opacity -Use opacity to specify the series area fill color. +Set the series area fill color using the **Fill opacity** slider. ![Fill opacity examples](/static/img/docs/time-series-panel/fill-opacity.png) #### Gradient mode -Gradient mode specifies the gradient fill, which is based on the series color. To change the color, use the standard color scheme field option. For more information, refer to [Color scheme](ref:color-scheme). +Choose a gradient mode to control the gradient fill, which is based on the series color. To change the color, use the standard color scheme field option. For more information, refer to [Color scheme](ref:color-scheme). -- **None:** No gradient fill. This is the default setting. -- **Opacity:** An opacity gradient where the opacity of the fill increases as y-axis values increase. -- **Hue:** A subtle gradient that is based on the hue of the series color. -- **Scheme:** A color gradient defined by your [Color scheme](ref:color-scheme). This setting is used for the fill area and line. For more information about scheme, refer to [Scheme gradient mode](#scheme-gradient-mode). +- **None** - No gradient fill. This is the default setting. +- **Opacity** - An opacity gradient where the opacity of the fill increases as y-axis values increase. +- **Hue** - A subtle gradient that's based on the hue of the series color. +- **Scheme** - A color gradient defined by your [Color scheme](ref:color-scheme). This setting is used for the fill area and line. For more information about scheme, refer to [Scheme gradient mode](#scheme-gradient-mode). -Gradient appearance is influenced by the **Fill opacity** setting. The following image show, the **Fill opacity** is set to 50. +Gradient appearance is influenced by the **Fill opacity** setting. The following image shows the **Fill opacity** set to 50. ![Gradient mode examples](/static/img/docs/time-series-panel/gradient-modes-v9.png) ##### Scheme gradient mode -The **Gradient mode** option located under the **Graph styles** has a mode named **Scheme**. When you enable **Scheme**, the line or bar receives a gradient color defined from the selected **Color scheme**. +The **Gradient mode** option located under the **Graph styles** section has a mode called **Scheme**. When you enable **Scheme**, the line or bar receives a gradient color defined from the selected **Color scheme**. ###### From thresholds -If the **Color scheme** is set to **From thresholds (by value)** and **Gradient mode** is set to **Scheme**, then the line or bar color changes as they cross the defined thresholds. +If the **Color scheme** is set to **From thresholds (by value)** and **Gradient mode** is set to **Scheme**, then the line or bar color changes as it crosses the defined thresholds. {{< figure src="/static/img/docs/time-series-panel/gradient_mode_scheme_thresholds_line.png" max-width="1200px" alt="Colors scheme: From thresholds" >}} @@ -242,11 +242,11 @@ The following image shows a line chart with the **Green-Yellow-Red (by value)** #### Line style -Set the style of the line. To change the color, use the standard [color scheme](ref:color-scheme) field option. +Choose a solid, dashed, or dotted line style: -- **Solid:** Display a solid line. This is the default setting. -- **Dash:** Display a dashed line. When you choose this option, a list appears for you to select the length and gap (length, gap) for the line dashes. Dash spacing set to 10, 10 (default). -- **Dots:** Display dotted lines. When you choose this option, a list appears for you to select the gap (length = 0, gap) for the dot spacing. Dot spacing set to 0, 10 (default) +- **Solid** - Display a solid line. This is the default setting. +- **Dash** - Display a dashed line. When you choose this option, a list appears for you to select the length and gap (length, gap) for the line dashes. Dash spacing is 10, 10 by default. +- **Dots** - Display dotted lines. When you choose this option, a list appears for you to select the gap (length = 0, gap) for the dot spacing. Dot spacing is 0, 10 by default. ![Line styles examples](/static/img/docs/time-series-panel/line-styles-examples-v9.png) @@ -254,21 +254,23 @@ Set the style of the line. To change the color, use the standard [color scheme]( {{< docs/shared lookup="visualizations/disconnect-values.md" source="grafana" version="" leveloffset="+1" >}} +To change the color, use the standard [color scheme](ref:color-scheme) field option. + #### Show points -You can configure your visualization to add points to lines or bars. +Set whether to show data points as lines or bars. Choose from the following: -- **Auto:** Grafana determines to show or not to show points based on the density of the data. If the density is low, then points appear. -- **Always:** Show the points regardless of how dense the data set is. -- **Never:** Do not show points. +- **Auto** - Grafana determines a point's visibility based on the density of the data. If the density is low, then points appear. +- **Always** - Show the points regardless of how dense the data set is. +- **Never** - Don't show points. #### Stack series -_Stacking_ allows Grafana to display series on top of each other. Be cautious when using stacking in the visualization as it can easily create misleading graphs. To read more about why stacking might not be the best approach, refer to [The issue with stacking](https://www.data-to-viz.com/caveat/stacking.html). +Set whether Grafana stacks or displays series on top of each other. Be cautious when using stacking because it can create misleading graphs. To read more about why stacking might not be the best approach, refer to [The issue with stacking](https://www.data-to-viz.com/caveat/stacking.html). Choose from the following: -- **Off:** Turns off series stacking. When **Off**, all series share the same space in the visualization. -- **Normal:** Stacks series on top of each other. -- **100%:** Stack by percentage where all series add up to 100%. +- **Off** - Turns off series stacking. When **Off**, all series share the same space in the visualization. +- **Normal** - Stacks series on top of each other. +- **100%** - Stack by percentage where all series add up to 100%. ##### Stack series in groups @@ -283,7 +285,7 @@ The stacking group option is only available as an override. For more information #### Bar alignment -Set the position of the bar relative to a data point. In the examples below, **Show points** is set to **Always** which makes it easier to see the difference this setting makes. The points do not change; the bars change in relationship to the points. +Set the position of the bar relative to a data point. In the examples below, **Show points** is set to **Always** which makes it easier to see the difference this setting makes. The points don't change, but the bars change in relationship to the points. Choose from the following: - **Before** ![Bar alignment before icon](/static/img/docs/time-series-panel/bar-alignment-before.png) The bar is drawn before the point. The point is placed on the trailing corner of the bar. diff --git a/docs/sources/setup-grafana/configure-grafana/_index.md b/docs/sources/setup-grafana/configure-grafana/_index.md index 657be0218b3fe..dae820f5ec6ce 100644 --- a/docs/sources/setup-grafana/configure-grafana/_index.md +++ b/docs/sources/setup-grafana/configure-grafana/_index.md @@ -1552,7 +1552,7 @@ Sets a global limit on number of correlations that can be created. Default is -1 ## [unified_alerting] -For more information about the Grafana alerts, refer to [About Grafana Alerting]({{< relref "../../alerting" >}}). +For more information about the Grafana alerts, refer to [Grafana Alerting]({{< relref "../../alerting" >}}). ### enabled @@ -1580,6 +1580,10 @@ The interval string is a possibly signed sequence of decimal numbers, followed b The Redis server address that should be connected to. +{{< admonition type="note" >}} +For more information on Redis, refer to [Enable alerting high availability using Redis](https://grafana.com/docs/grafana//alerting/set-up/configure-high-availability/#enable-alerting-high-availability-using-redis). +{{< /admonition >}} + ### ha_redis_username The username that should be used to authenticate with the Redis server. diff --git a/docs/sources/setup-grafana/installation/docker/index.md b/docs/sources/setup-grafana/installation/docker/index.md index 47aa7d0f4a099..7e7e0bef06f4a 100644 --- a/docs/sources/setup-grafana/installation/docker/index.md +++ b/docs/sources/setup-grafana/installation/docker/index.md @@ -221,7 +221,6 @@ To run the latest stable version of Grafana using Docker Compose, complete the f For example: ```bash - version: "3.8" services: grafana: image: grafana/grafana-enterprise @@ -279,7 +278,6 @@ To use Docker volumes for persistent storage, complete the following steps: 1. Add the following code into the `docker-compose.yaml` file. ```yaml - version: '3.8' services: grafana: image: grafana/grafana-enterprise @@ -324,7 +322,6 @@ To use bind mounts, complete the following steps: 1. Now, add the following code into the `docker-compose.yaml` file. ```yaml - version: '3.8' services: grafana: image: grafana/grafana-enterprise @@ -351,7 +348,6 @@ To use bind mounts, complete the following steps: The following example runs the latest stable version of Grafana, listening on port 3000, with the container named `grafana`, persistent storage in the `grafana-storage` docker volume, the server root URL set, and the official [clock panel](/grafana/plugins/grafana-clock-panel/) plugin installed. ```bash -version: "3.8" services: grafana: image: grafana/grafana-enterprise diff --git a/docs/sources/shared/alerts/alerting_provisioning.md b/docs/sources/shared/alerts/alerting_provisioning.md index d8663fdfb4712..6146a1cf36961 100644 --- a/docs/sources/shared/alerts/alerting_provisioning.md +++ b/docs/sources/shared/alerts/alerting_provisioning.md @@ -6,29 +6,15 @@ labels: title: 'Alerting Provisioning HTTP API ' --- -The Alerting provisioning API can be used to create, modify, and delete resources relevant to [Grafana-managed alerts]({{< relref "/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule" >}}). It is the one used by our [Grafana Terraform provider](https://registry.terraform.io/providers/grafana/grafana/latest/docs). +The Alerting Provisioning HTTP API can be used to create, modify, and delete resources relevant to Grafana-managed alerts. This API is the one used by our [Grafana Terraform provider](https://registry.terraform.io/providers/grafana/grafana/latest/docs). -To manage resources related to [data source-managed alerts]({{< relref "/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule" >}}), including recording rules, use the [Mimir tool](https://grafana.com/docs/mimir/latest/manage/tools/mimirtool/) and [Cortex tool](https://github.com/grafana/cortex-tools#cortextool). +For more information on the differences between Grafana-managed and data source-managed alerts, refer to [Introduction to alert rules](https://grafana.com/docs/grafana//alerting/fundamentals/alert-rules/). -## Information +> If you are running Grafana Enterprise, you need to add specific permissions for some endpoints. For more information, refer to [Role-based access control permissions](https://grafana.com/docs/grafana//administration/roles-and-permissions/access-control/custom-role-actions-scopes/). -### Version +## Grafana-managed endpoints -1.1.0 - -## Content negotiation - -### Consumes - -- application/json - -### Produces - -- application/json -- text/yaml -- application/yaml - -## All endpoints +Note that the JSON format from most of the following endpoints is not fully compatible with [provisioning via configuration JSON files](https://grafana.com/docs/grafana//alerting/set-up/provision-alerting-resources/file-provisioning/). ### Alert rules @@ -45,13 +31,18 @@ To manage resources related to [data source-managed alerts]({{< relref "/docs/gr | GET | /api/v1/provisioning/alert-rules | [route get alert rules](#route-get-alert-rules) | Get all the alert rules. | | GET | /api/v1/provisioning/alert-rules/export | [route get alert rules export](#route-get-alert-rules-export) | Export all alert rules in provisioning file format. | -#### Example alert rules template +**Example request for new alert rule:** + +```http +POST /api/v1/provisioning/alert-rules +Accept: application/json +Content-Type: application/json +Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk -```json { "title": "TEST-API_1", "ruleGroup": "API", - "folderUID": "FOLDER", + "folderUID": "SET_FOLDER_UID", "noDataState": "OK", "execErrState": "OK", "for": "5m", @@ -72,7 +63,7 @@ To manage resources related to [data source-managed alerts]({{< relref "/docs/gr "from": 600, "to": 0 }, - "datasourceUid": " XXXXXXXXX-XXXXXXXXX-XXXXXXXXXX", + "datasourceUid": "XXXXXXXXX-XXXXXXXXX-XXXXXXXXXX", "model": { "expr": "up", "hide": false, @@ -122,6 +113,99 @@ To manage resources related to [data source-managed alerts]({{< relref "/docs/gr } ] } + +``` + +#### Example Response: + +```http +HTTP/1.1 201 Created +Content-Type: application/json + +{ + "id": 1, + "uid": "XXXXXXXXX", + "orgID": 1, + "folderUID": "SET_FOLDER_UID", + "ruleGroup": "API3", + "title": "TEST-API_1", + "condition": "B", + "data": [ + { + "refId": "A", + "queryType": "", + "relativeTimeRange": { + "from": 600, + "to": 0 + }, + "datasourceUid": "XXXXXXXXX-XXXXXXXXX-XXXXXXXXXX", + "model": { + "expr": "up", + "hide": false, + "intervalMs": 1000, + "maxDataPoints": 43200, + "refId": "A" + } + }, + { + "refId": "B", + "queryType": "", + "relativeTimeRange": { + "from": 0, + "to": 0 + }, + "datasourceUid": "-100", + "model": { + "conditions": [ + { + "evaluator": { + "params": [ + 6 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "datasource": { + "type": "__expr__", + "uid": "-100" + }, + "hide": false, + "intervalMs": 1000, + "maxDataPoints": 43200, + "refId": "B", + "type": "classic_conditions" + } + } + ], + "updated": "2024-08-02T13:19:32.609640048Z", + "noDataState": "OK", + "execErrState": "OK", + "for": "5m", + "annotations": { + "summary": "test_api_1" + }, + "labels": { + "API": "test1" + }, + "provenance": "api", + "isPaused": false, + "notification_settings": null, + "record": null +} ``` ### Contact points @@ -134,6 +218,34 @@ To manage resources related to [data source-managed alerts]({{< relref "/docs/gr | PUT | /api/v1/provisioning/contact-points/:uid | [route put contactpoint](#route-put-contactpoint) | Update an existing contact point. | | GET | /api/v1/provisioning/contact-points/export | [route get contactpoints export](#route-get-contactpoints-export) | Export all contact points in provisioning file format. | +**Example Request for all the contact points:** + +```http +GET /api/v1/provisioning/contact-points +Accept: application/json +Content-Type: application/json +Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk +``` + +**Example Response:** + +```http +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "uid": "", + "name": "email receiver", + "type": "email", + "settings": { + "addresses": "" + }, + "disableResolveMessage": false + } +] +``` + ### Notification policies | Method | URI | Name | Summary | @@ -143,6 +255,38 @@ To manage resources related to [data source-managed alerts]({{< relref "/docs/gr | PUT | /api/v1/provisioning/policies | [route put policy tree](#route-put-policy-tree) | Sets the notification policy tree. | | GET | /api/v1/provisioning/policies/export | [route get policy tree export](#route-get-policy-tree-export) | Export the notification policy tree in provisioning file format. | +**Example Request for exporting the notification policy tree in YAML format:** + +```http +GET /api/v1/provisioning/policies/export?format=yaml +Accept: application/json +Content-Type: application/json +Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk +``` + +**Example Response:** + +```http +HTTP/1.1 200 OK +Content-Type: text/yaml + +apiVersion: 1 +policies: + - orgId: 1 + receiver: My Contact Email Point + group_by: + - grafana_folder + - alertname + routes: + - receiver: My Contact Email Point + object_matchers: + - - monitor + - = + - testdata + mute_time_intervals: + - weekends +``` + ### Mute timings | Method | URI | Name | Summary | @@ -155,6 +299,38 @@ To manage resources related to [data source-managed alerts]({{< relref "/docs/gr | GET | /api/v1/provisioning/mute-timings/export | [route get mute timings export](#route-get-mute-timings-export) | Export all mute timings in provisioning file format. | | GET | /api/v1/provisioning/mute-timings/:name/export | [route get mute timing export](#route-get-mute-timing-export) | Export a mute timing in provisioning file format. | +**Example Request for all mute timings:** + +```http +GET /api/v1/provisioning/mute-timings +Accept: application/json +Content-Type: application/json +Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk +``` + +**Example Response:** + +```http +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "name": "weekends", + "time_intervals": [ + { + "weekdays": [ + "saturday", + "sunday" + ] + } + ], + "version": "", + "provenance": "file" + } +] +``` + ### Templates | Method | URI | Name | Summary | @@ -164,7 +340,36 @@ To manage resources related to [data source-managed alerts]({{< relref "/docs/gr | GET | /api/v1/provisioning/templates | [route get templates](#route-get-templates) | Get all notification templates. | | PUT | /api/v1/provisioning/templates/:name | [route put template](#route-put-template) | Create or update a notification template. | -## Edit resources in the Grafana UI +**Example Request for all notification templates:** + +```http +GET /api/v1/provisioning/templates +Accept: application/json +Content-Type: application/json +Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk +``` + +**Example Response:** + +```http +HTTP/1.1 200 OK +Content-Type: application/json + +[ + { + "name": "custom_email.message", + "template": "{{ define \"custom_email.message\" }}\n Custom alert!\n{{ end }}", + "provenance": "file" + }, + { + "name": "custom_email.subject", + "template": "{{ define \"custom_email.subject\" }}\n{{ len .Alerts.Firing }} firing alert(s), {{ len .Alerts.Resolved }} resolved alert(s)\n{{ end }}", + "provenance": "file" + } +] +``` + +### Edit resources in the Grafana UI By default, you cannot edit API-provisioned alerting resources in Grafana. To enable editing these resources in the Grafana UI, add the `X-Disable-Provenance` header to the following requests in the API: @@ -177,6 +382,18 @@ By default, you cannot edit API-provisioned alerting resources in Grafana. To en To reset the notification policy tree to the default and unlock it for editing in the Grafana UI, use the `DELETE /api/v1/provisioning/policies` endpoint. +## Data source-managed resources + +The Alerting Provisioning HTTP API can only be used to manage Grafana-managed alert resources. To manage resources related to [data source-managed alerts](https://grafana.com/docs/grafana//alerting/alerting-rules/create-mimir-loki-managed-rule/), consider the following tools: + +- [mimirtool](https://grafana.com/docs/mimir//manage/tools/mimirtool/): to interact with the Mimir alertmanager and ruler configuration. +- [cortex-tools](https://github.com/grafana/cortex-tools#cortextool): to interact with the Cortex alertmanager and ruler configuration. +- [lokitool](https://grafana.com/docs/loki//alert/#lokitool): to configure the Loki Ruler. + +Alternatively, the [Grafana Alerting API](https://editor.swagger.io/?url=https://raw.githubusercontent.com/grafana/grafana/main/pkg/services/ngalert/api/tooling/post.json) can be used to access data from data source-managed alerts. This API is primarily intended for internal usage, with the exception of the `/api/v1/provisioning/` endpoints. It's important to note that internal APIs may undergo changes without prior notice and are not officially supported for user consumption. + +For Prometheus, `amtool` can also be used to interact with the [AlertManager API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/prometheus/alertmanager/main/api/v2/openapi.yaml#/). + ## Paths ### Delete a specific alert rule by UID. (_RouteDeleteAlertRule_) @@ -216,10 +433,6 @@ Status: No Content DELETE /api/v1/provisioning/contact-points/:uid ``` -#### Consumes - -- application/json - #### Parameters | Name | Source | Type | Go type | Separator | Required | Default | Description | @@ -884,10 +1097,6 @@ Status: Not Found POST /api/v1/provisioning/alert-rules ``` -#### Consumes - -- application/json - #### Parameters {{% responsive-table %}} @@ -930,10 +1139,6 @@ Status: Bad Request POST /api/v1/provisioning/contact-points ``` -#### Consumes - -- application/json - #### Parameters {{% responsive-table %}} @@ -976,10 +1181,6 @@ Status: Bad Request POST /api/v1/provisioning/mute-timings ``` -#### Consumes - -- application/json - #### Parameters {{% responsive-table %}} @@ -1022,10 +1223,6 @@ Status: Bad Request PUT /api/v1/provisioning/alert-rules/:uid ``` -#### Consumes - -- application/json - #### Parameters {{% responsive-table %}} @@ -1069,10 +1266,6 @@ Status: Bad Request PUT /api/v1/provisioning/folder/:folderUid/rule-groups/:group ``` -#### Consumes - -- application/json - #### Parameters {{% responsive-table %}} @@ -1117,10 +1310,6 @@ Status: Bad Request PUT /api/v1/provisioning/contact-points/:uid ``` -#### Consumes - -- application/json - #### Parameters {{% responsive-table %}} @@ -1164,10 +1353,6 @@ Status: Bad Request PUT /api/v1/provisioning/mute-timings/:name ``` -#### Consumes - -- application/json - #### Parameters {{% responsive-table %}} @@ -1211,10 +1396,6 @@ Status: Bad Request PUT /api/v1/provisioning/policies ``` -#### Consumes - -- application/json - #### Parameters {{% responsive-table %}} @@ -1257,10 +1438,6 @@ Status: Bad Request PUT /api/v1/provisioning/templates/:name ``` -#### Consumes - -- application/json - {{% responsive-table %}} #### Parameters @@ -1304,10 +1481,6 @@ Status: Bad Request DELETE /api/v1/provisioning/policies ``` -#### Consumes - -- application/json - #### All responses | Code | Status | Description | Has headers | Schema | diff --git a/docs/sources/shared/visualizations/config-options-intro.md b/docs/sources/shared/visualizations/config-options-intro.md new file mode 100644 index 0000000000000..94173717f1139 --- /dev/null +++ b/docs/sources/shared/visualizations/config-options-intro.md @@ -0,0 +1,7 @@ +--- +title: Configuration options intro text +comments: | + This file is used in the following in all visualizations except: alert list, annotiations list, logs, news, text +--- + +The following section describes the configuration options available in the panel editor pane for this visualization. These options are, as much as possible, ordered as they appear in Grafana. diff --git a/docs/sources/shared/visualizations/connect-null-values.md b/docs/sources/shared/visualizations/connect-null-values.md index d1190a63a92b2..50660321f93ac 100644 --- a/docs/sources/shared/visualizations/connect-null-values.md +++ b/docs/sources/shared/visualizations/connect-null-values.md @@ -6,6 +6,6 @@ title: Connect null values Choose how null values, which are gaps in the data, appear on the graph. Null values can be connected to form a continuous line or set to a threshold above which gaps in the data are no longer connected. -- **Never:** Time series data points with gaps in the data are never connected. -- **Always:** Time series data points with gaps in the data are always connected. -- **Threshold:** Specify a threshold above which gaps in the data are no longer connected. This can be useful when the connected gaps in the data are of a known size and/or within a known range, and gaps outside this range should no longer be connected. +- **Never** - Time series data points with gaps in the data are never connected. +- **Always** - Time series data points with gaps in the data are always connected. +- **Threshold** - Specify a threshold above which gaps in the data are no longer connected. This can be useful when the connected gaps in the data are of a known size and/or within a known range, and gaps outside this range should no longer be connected. diff --git a/docs/sources/shared/visualizations/disconnect-values.md b/docs/sources/shared/visualizations/disconnect-values.md index 72b40153a2d61..cba32cfc6fb05 100644 --- a/docs/sources/shared/visualizations/disconnect-values.md +++ b/docs/sources/shared/visualizations/disconnect-values.md @@ -6,5 +6,5 @@ title: Disconnect values Choose whether to set a threshold above which values in the data should be disconnected. -- **Never:** Time series data points in the data are never disconnected. -- **Threshold:** Specify a threshold above which values in the data are disconnected. This can be useful when desired values in the data are of a known size and/or within a known range, and values outside this range should no longer be connected. +- **Never** - Time series data points in the data are never disconnected. +- **Threshold** - Specify a threshold above which values in the data are disconnected. This can be useful when desired values in the data are of a known size and/or within a known range, and values outside this range should no longer be connected. diff --git a/docs/sources/shared/visualizations/legend-options-1.md b/docs/sources/shared/visualizations/legend-options-1.md index 30123dda0d436..a81d1aa45fc8a 100644 --- a/docs/sources/shared/visualizations/legend-options-1.md +++ b/docs/sources/shared/visualizations/legend-options-1.md @@ -12,6 +12,6 @@ Legend options control the series names and statistics that appear under or to t | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Visibility | Toggle the switch to turn the legend on or off. | | Mode | Use these settings to define how the legend appears in your visualization. **List** displays the legend as a list. This is a default display mode of the legend. **Table** displays the legend as a table. | -| Placement | Choose where to display the legend. **Bottom -** Below the graph. **Right -** To the right of the graph. | +| Placement | Choose where to display the legend. **Bottom** places the legend below the graph. **Right** places the legend to the right of the graph. | | Width | Control how wide the legend is when placed on the right side of the visualization. This option is only displayed if you set the legend placement to **Right**. | | Values | Choose which of the [standard calculations](../../query-transform-data/calculation-types/) to show in the legend. You can have more than one. | diff --git a/docs/sources/shared/visualizations/multiple-y-axes.md b/docs/sources/shared/visualizations/multiple-y-axes.md index 243f73bda5cd7..4d74d3b9501d5 100644 --- a/docs/sources/shared/visualizations/multiple-y-axes.md +++ b/docs/sources/shared/visualizations/multiple-y-axes.md @@ -1,9 +1,9 @@ --- -title: Display multiple y-axes +title: Multiple y-axes --- -# Display multiple y-axes +# Multiple y-axes -In some cases, you may want to display multiple y-axes. For example, if you have a dataset showing both temperature and humidity over time, you may want to show two y-axes with different units for these two series. +In some cases, you might want to display multiple y-axes. For example, if you have a dataset showing both temperature and humidity over time, you might want to show two y-axes with different units for the two series. -You can do this by [adding field overrides]({{< relref "../../panels-visualizations/configure-overrides#add-a-field-override" >}}). Follow the steps as many times as required to add as many y-axes as you need. +You can configure multiple y-axes and control where they're displayed in the visualization by adding field overrides. [This example of a dataset that includes temperature and humidity](../../configure-overrides/#example-2-format-temperature-and-humidity) describes how you can configure that. Repeat the steps for every y-axis you wish to display. diff --git a/docs/sources/shared/visualizations/overrides-options.md b/docs/sources/shared/visualizations/overrides-options.md index 71e7ce8ebcd64..21b910af4cb4e 100644 --- a/docs/sources/shared/visualizations/overrides-options.md +++ b/docs/sources/shared/visualizations/overrides-options.md @@ -6,7 +6,7 @@ comments: | Overrides allow you to customize visualization settings for specific fields or series. When you add an override rule, it targets a particular set of fields and lets you define multiple options for how that field is displayed. -Choose from one the following override options: +Choose from the following override options: | Option | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | diff --git a/docs/sources/shared/visualizations/panel-options.md b/docs/sources/shared/visualizations/panel-options.md index 5455933bb54c4..c013457d19187 100644 --- a/docs/sources/shared/visualizations/panel-options.md +++ b/docs/sources/shared/visualizations/panel-options.md @@ -4,4 +4,4 @@ comments: | This file is used in all visualizations pages --- -In the **Panel options** section of the panel editor pane, you set basic options like the panel title and description. You can also configure repeating panels in this section. To learn more, refer to [Configure panel options](../../configure-panel-options/). +In the **Panel options** section of the panel editor pane, set basic options like panel title and description, as well as panel links. To learn more, refer to [Configure panel options](../../configure-panel-options/). diff --git a/docs/sources/shared/visualizations/standard-options.md b/docs/sources/shared/visualizations/standard-options.md index f4d84606fd5d3..db489bd09e343 100644 --- a/docs/sources/shared/visualizations/standard-options.md +++ b/docs/sources/shared/visualizations/standard-options.md @@ -6,8 +6,6 @@ comments: | **Standard options** in the panel editor pane let you change how field data is displayed in your visualizations. When you set a standard option, the change is applied to all fields or series. For more granular control over the display of fields, refer to [Configure overrides](../../configure-overrides/). -You can customize the following standard options: - | Option | Description | | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | Unit | Choose which unit a field should use. | diff --git a/docs/sources/shared/visualizations/thresholds-options-1.md b/docs/sources/shared/visualizations/thresholds-options-1.md index 264e53839cadc..3b2fc6b8f6ba2 100644 --- a/docs/sources/shared/visualizations/thresholds-options-1.md +++ b/docs/sources/shared/visualizations/thresholds-options-1.md @@ -8,7 +8,7 @@ comments: | A threshold is a value or limit you set for a metric that’s reflected visually when it’s met or exceeded. Thresholds are one way you can conditionally style and color your visualizations based on query results. -Set the following options: +For each threshold, set the following options: | Option | Description | | --------------- | ------------------------------------------------------------------------------------ | diff --git a/docs/sources/whatsnew/whats-new-in-v11-1.md b/docs/sources/whatsnew/whats-new-in-v11-1.md index 84123c5e0f1ba..914523a7f78d1 100644 --- a/docs/sources/whatsnew/whats-new-in-v11-1.md +++ b/docs/sources/whatsnew/whats-new-in-v11-1.md @@ -44,6 +44,10 @@ Learn more about the table panel in our [table panel documentation](https://graf {{< youtube id="wBLxYp2BLAU" >}} +{{< admonition type="note" >}} +Text wrapping is in [public preview](https://grafana.com/docs/release-life-cycle/#public-preview), however, it’s available to use by default. We’d love hear from you about how this new feature is working. To provide feedback, you can open an issue in the [Grafana GitHub repository](https://github.com/grafana/grafana). +{{< /admonition >}} + #### Stat visualization percent change color mode options _Generally available in all editions of Grafana_ diff --git a/go.mod b/go.mod index 9c5555ffae41e..c81a561bdf267 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( cuelang.org/go v0.6.0-0.dev // @grafana/grafana-as-code filippo.io/age v1.1.1 // @grafana/identity-access-team github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // @grafana/partner-datasources - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 // @grafana/grafana-backend-group + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // @grafana/grafana-backend-group github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.9.0 // @grafana/grafana-backend-group github.com/Azure/azure-storage-blob-go v0.15.0 // @grafana/grafana-backend-group github.com/Azure/go-autorest/autorest v0.11.29 // @grafana/grafana-backend-group @@ -210,7 +210,7 @@ require ( cloud.google.com/go/iam v1.1.6 // indirect github.com/Azure/azure-pipeline-go v0.2.3 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect @@ -443,6 +443,8 @@ require ( sigs.k8s.io/yaml v1.3.0 // indirect; @grafana-app-platform-squad ) +require github.com/hashicorp/go-retryablehttp v0.7.7 // indirect + // Use fork of crewjam/saml with fixes for some issues until changes get merged into upstream replace github.com/crewjam/saml => github.com/grafana/saml v0.4.15-0.20240523142256-cc370b98af7c diff --git a/go.sum b/go.sum index 9e53d18848631..a5290f1a726a1 100644 --- a/go.sum +++ b/go.sum @@ -1371,6 +1371,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3Q github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 h1:FDif4R1+UUR+00q6wquyX90K7A8dN+R5E8GEadoP7sU= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2/go.mod h1:aiYBYui4BJ/BJCAIKs92XiPyQfTaBWqvHujDwKb6CBU= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= @@ -1379,6 +1381,8 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aov github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI= github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 h1:LqbJ/WzJUwBf8UiaSzgX7aMclParm9/5Vgp+TY51uBQ= github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2/go.mod h1:yInRyqWXAuaPrgI7p70+lDDgh3mlBohis29jGMISnmc= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.9.0 h1:TOFrNxfjslms5nLLIMjW7N0+zSALX4KiGsptmpb16AA= github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.9.0/go.mod h1:EAyXOW1F6BTJPiK2pDvmnvxOHPxoTYWoqBeIlql+QhI= github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0 h1:Lg6BW0VPmCwcMlvOviL3ruHFO+H9tZNqscK0AeuFjGM= @@ -2276,8 +2280,6 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grafana/alerting v0.0.0-20240606211712-071c8609797a h1:MvrEgxNxmUqaFWkBtRlbgxStbdD8FcmtjlRp98bmMJU= -github.com/grafana/alerting v0.0.0-20240606211712-071c8609797a/go.mod h1:U7Ta3K4T7jVgqGSYuPsfuPKHFiL2GbCZSHa3nHjmCos= github.com/grafana/alerting v0.0.0-20240712181403-02e012d6dd7f h1:YXJj/6K9tzTZFeUyf39Q/zFoHKUdmz+zLNZUIOzP8Do= github.com/grafana/alerting v0.0.0-20240712181403-02e012d6dd7f/go.mod h1:U7Ta3K4T7jVgqGSYuPsfuPKHFiL2GbCZSHa3nHjmCos= github.com/grafana/authlib v0.0.0-20240515154731-fe4779055ef4 h1:Bfa397TXkM0X97MhbCC+fNSwVtg21c0Mg5STes1dRug= @@ -2398,8 +2400,9 @@ github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOs github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= diff --git a/lerna.json b/lerna.json index 48193fd5e2e6e..5dbbb0d9639c2 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "npmClient": "yarn", - "version": "11.1.4" + "version": "11.1.5" } diff --git a/package.json b/package.json index 1ebce0adcdbae..f20c812fc1909 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "license": "AGPL-3.0-only", "private": true, "name": "grafana", - "version": "11.1.4", + "version": "11.1.5", "repository": "github:grafana/grafana", "scripts": { "build": "NODE_ENV=production nx exec --verbose -- webpack --config scripts/webpack/webpack.prod.js", diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index 16974cf765135..a7bf109c4b485 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/data", - "version": "11.1.4", + "version": "11.1.5", "description": "Grafana Data Library", "keywords": [ "typescript" @@ -36,7 +36,7 @@ }, "dependencies": { "@braintree/sanitize-url": "7.0.1", - "@grafana/schema": "11.1.4", + "@grafana/schema": "11.1.5", "@types/d3-interpolate": "^3.0.0", "@types/string-hash": "1.1.3", "d3-interpolate": "3.0.1", diff --git a/packages/grafana-e2e-selectors/package.json b/packages/grafana-e2e-selectors/package.json index 559fc158d9005..6eb17aa047e35 100644 --- a/packages/grafana-e2e-selectors/package.json +++ b/packages/grafana-e2e-selectors/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/e2e-selectors", - "version": "11.1.4", + "version": "11.1.5", "description": "Grafana End-to-End Test Selectors Library", "keywords": [ "cli", diff --git a/packages/grafana-eslint-rules/package.json b/packages/grafana-eslint-rules/package.json index 76361bd1b6486..6d71193fdd27f 100644 --- a/packages/grafana-eslint-rules/package.json +++ b/packages/grafana-eslint-rules/package.json @@ -1,7 +1,7 @@ { "name": "@grafana/eslint-plugin", "description": "ESLint rules for use within the Grafana repo. Not suitable (or supported) for external use.", - "version": "11.1.4", + "version": "11.1.5", "main": "./index.cjs", "author": "Grafana Labs", "license": "Apache-2.0", diff --git a/packages/grafana-flamegraph/package.json b/packages/grafana-flamegraph/package.json index 60dbc77119675..eb8216b7a9c90 100644 --- a/packages/grafana-flamegraph/package.json +++ b/packages/grafana-flamegraph/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/flamegraph", - "version": "11.1.4", + "version": "11.1.5", "description": "Grafana flamegraph visualization component", "keywords": [ "grafana", @@ -44,8 +44,8 @@ ], "dependencies": { "@emotion/css": "11.11.2", - "@grafana/data": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/data": "11.1.5", + "@grafana/ui": "11.1.5", "@leeoniya/ufuzzy": "1.0.14", "d3": "^7.8.5", "lodash": "4.17.21", diff --git a/packages/grafana-icons/package.json b/packages/grafana-icons/package.json index 12ecddd9fe835..275d665517d1b 100644 --- a/packages/grafana-icons/package.json +++ b/packages/grafana-icons/package.json @@ -1,6 +1,6 @@ { "name": "@grafana/saga-icons", - "version": "11.1.4", + "version": "11.1.5", "private": true, "description": "Icons for Grafana", "author": "Grafana Labs", diff --git a/packages/grafana-o11y-ds-frontend/package.json b/packages/grafana-o11y-ds-frontend/package.json index 5769df330e59a..c30cc8d042943 100644 --- a/packages/grafana-o11y-ds-frontend/package.json +++ b/packages/grafana-o11y-ds-frontend/package.json @@ -3,7 +3,7 @@ "license": "AGPL-3.0-only", "name": "@grafana/o11y-ds-frontend", "private": true, - "version": "11.1.4", + "version": "11.1.5", "description": "Library to manage traces in Grafana.", "sideEffects": false, "repository": { @@ -18,12 +18,12 @@ }, "dependencies": { "@emotion/css": "11.11.2", - "@grafana/data": "11.1.4", - "@grafana/e2e-selectors": "11.1.4", + "@grafana/data": "11.1.5", + "@grafana/e2e-selectors": "11.1.5", "@grafana/experimental": "1.7.11", - "@grafana/runtime": "11.1.4", - "@grafana/schema": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/runtime": "11.1.5", + "@grafana/schema": "11.1.5", + "@grafana/ui": "11.1.5", "react-select": "5.8.0", "react-use": "17.5.0", "rxjs": "7.8.1", diff --git a/packages/grafana-plugin-configs/package.json b/packages/grafana-plugin-configs/package.json index 979119d75665e..df7e78ae73363 100644 --- a/packages/grafana-plugin-configs/package.json +++ b/packages/grafana-plugin-configs/package.json @@ -2,7 +2,7 @@ "name": "@grafana/plugin-configs", "description": "Shared dependencies and files for core plugins", "private": true, - "version": "11.1.4", + "version": "11.1.5", "dependencies": { "tslib": "2.6.3" }, diff --git a/packages/grafana-prometheus/package.json b/packages/grafana-prometheus/package.json index 1aba766f55680..cb9a4dd3eca0d 100644 --- a/packages/grafana-prometheus/package.json +++ b/packages/grafana-prometheus/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "AGPL-3.0-only", "name": "@grafana/prometheus", - "version": "11.1.4", + "version": "11.1.5", "description": "Grafana Prometheus Library", "keywords": [ "typescript" @@ -38,12 +38,12 @@ "dependencies": { "@emotion/css": "11.11.2", "@floating-ui/react": "0.26.16", - "@grafana/data": "11.1.4", + "@grafana/data": "11.1.5", "@grafana/experimental": "1.7.11", "@grafana/faro-web-sdk": "1.7.3", - "@grafana/runtime": "11.1.4", - "@grafana/schema": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/runtime": "11.1.5", + "@grafana/schema": "11.1.5", + "@grafana/ui": "11.1.5", "@leeoniya/ufuzzy": "1.0.14", "@lezer/common": "1.2.1", "@lezer/highlight": "1.2.0", @@ -76,7 +76,7 @@ }, "devDependencies": { "@emotion/eslint-plugin": "11.11.0", - "@grafana/e2e-selectors": "11.1.4", + "@grafana/e2e-selectors": "11.1.5", "@grafana/tsconfig": "^1.3.0-rc1", "@rollup/plugin-image": "3.0.3", "@rollup/plugin-node-resolve": "15.2.3", diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index 4a82da3502726..52eb40929baa2 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/runtime", - "version": "11.1.4", + "version": "11.1.5", "description": "Grafana Runtime Library", "keywords": [ "grafana", @@ -37,11 +37,11 @@ "postpack": "mv package.json.bak package.json" }, "dependencies": { - "@grafana/data": "11.1.4", - "@grafana/e2e-selectors": "11.1.4", + "@grafana/data": "11.1.5", + "@grafana/e2e-selectors": "11.1.5", "@grafana/faro-web-sdk": "^1.3.6", - "@grafana/schema": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/schema": "11.1.5", + "@grafana/ui": "11.1.5", "history": "4.10.1", "lodash": "4.17.21", "rxjs": "7.8.1", diff --git a/packages/grafana-schema/package.json b/packages/grafana-schema/package.json index b3b89c71b0c68..5c47acf178196 100644 --- a/packages/grafana-schema/package.json +++ b/packages/grafana-schema/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/schema", - "version": "11.1.4", + "version": "11.1.5", "description": "Grafana Schema Library", "keywords": [ "typescript" diff --git a/packages/grafana-schema/src/raw/composable/annotationslist/panelcfg/x/AnnotationsListPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/annotationslist/panelcfg/x/AnnotationsListPanelCfg_types.gen.ts index 8c95dac0a0905..89bb9844bf919 100644 --- a/packages/grafana-schema/src/raw/composable/annotationslist/panelcfg/x/AnnotationsListPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/annotationslist/panelcfg/x/AnnotationsListPanelCfg_types.gen.ts @@ -8,7 +8,7 @@ // // Run 'make gen-cue' from repository root to regenerate. -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options { limit: number; diff --git a/packages/grafana-schema/src/raw/composable/barchart/panelcfg/x/BarChartPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/barchart/panelcfg/x/BarChartPanelCfg_types.gen.ts index a87ea53e5cc10..3e31f77ec6cb7 100644 --- a/packages/grafana-schema/src/raw/composable/barchart/panelcfg/x/BarChartPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/barchart/panelcfg/x/BarChartPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options extends common.OptionsWithLegend, common.OptionsWithTooltip, common.OptionsWithTextFormatting { /** diff --git a/packages/grafana-schema/src/raw/composable/bargauge/panelcfg/x/BarGaugePanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/bargauge/panelcfg/x/BarGaugePanelCfg_types.gen.ts index e3e355f9238e1..3a471ddcef81c 100644 --- a/packages/grafana-schema/src/raw/composable/bargauge/panelcfg/x/BarGaugePanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/bargauge/panelcfg/x/BarGaugePanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options extends common.SingleStatBaseOptions { displayMode: common.BarGaugeDisplayMode; diff --git a/packages/grafana-schema/src/raw/composable/candlestick/panelcfg/x/CandlestickPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/candlestick/panelcfg/x/CandlestickPanelCfg_types.gen.ts index d6429df6c06d7..6335cafe1da13 100644 --- a/packages/grafana-schema/src/raw/composable/candlestick/panelcfg/x/CandlestickPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/candlestick/panelcfg/x/CandlestickPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export enum VizDisplayMode { Candles = 'candles', diff --git a/packages/grafana-schema/src/raw/composable/canvas/panelcfg/x/CanvasPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/canvas/panelcfg/x/CanvasPanelCfg_types.gen.ts index db9d344b68608..431139f9ff30e 100644 --- a/packages/grafana-schema/src/raw/composable/canvas/panelcfg/x/CanvasPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/canvas/panelcfg/x/CanvasPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as ui from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export enum HorizontalConstraint { Center = 'center', diff --git a/packages/grafana-schema/src/raw/composable/cloudwatch/dataquery/x/CloudWatchDataQuery_types.gen.ts b/packages/grafana-schema/src/raw/composable/cloudwatch/dataquery/x/CloudWatchDataQuery_types.gen.ts index 6f10a87a62b87..fb80053977c0b 100644 --- a/packages/grafana-schema/src/raw/composable/cloudwatch/dataquery/x/CloudWatchDataQuery_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/cloudwatch/dataquery/x/CloudWatchDataQuery_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface MetricStat { /** diff --git a/packages/grafana-schema/src/raw/composable/dashboardlist/panelcfg/x/DashboardListPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/dashboardlist/panelcfg/x/DashboardListPanelCfg_types.gen.ts index d0525a72bff54..8a7c39acf8b4e 100644 --- a/packages/grafana-schema/src/raw/composable/dashboardlist/panelcfg/x/DashboardListPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/dashboardlist/panelcfg/x/DashboardListPanelCfg_types.gen.ts @@ -8,7 +8,7 @@ // // Run 'make gen-cue' from repository root to regenerate. -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options { /** diff --git a/packages/grafana-schema/src/raw/composable/datagrid/panelcfg/x/DatagridPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/datagrid/panelcfg/x/DatagridPanelCfg_types.gen.ts index 42f4f1a0680af..39b7abbf459d7 100644 --- a/packages/grafana-schema/src/raw/composable/datagrid/panelcfg/x/DatagridPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/datagrid/panelcfg/x/DatagridPanelCfg_types.gen.ts @@ -8,7 +8,7 @@ // // Run 'make gen-cue' from repository root to regenerate. -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options { selectedSeries: number; diff --git a/packages/grafana-schema/src/raw/composable/debug/panelcfg/x/DebugPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/debug/panelcfg/x/DebugPanelCfg_types.gen.ts index 342dcc4ff1f77..97b7d2180030d 100644 --- a/packages/grafana-schema/src/raw/composable/debug/panelcfg/x/DebugPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/debug/panelcfg/x/DebugPanelCfg_types.gen.ts @@ -8,7 +8,7 @@ // // Run 'make gen-cue' from repository root to regenerate. -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export type UpdateConfig = { render: boolean, diff --git a/packages/grafana-schema/src/raw/composable/elasticsearch/dataquery/x/ElasticsearchDataQuery_types.gen.ts b/packages/grafana-schema/src/raw/composable/elasticsearch/dataquery/x/ElasticsearchDataQuery_types.gen.ts index e648a6f659676..f8930b974f9fe 100644 --- a/packages/grafana-schema/src/raw/composable/elasticsearch/dataquery/x/ElasticsearchDataQuery_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/elasticsearch/dataquery/x/ElasticsearchDataQuery_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export type BucketAggregation = (DateHistogram | Histogram | Terms | Filters | GeoHashGrid | Nested); diff --git a/packages/grafana-schema/src/raw/composable/gauge/panelcfg/x/GaugePanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/gauge/panelcfg/x/GaugePanelCfg_types.gen.ts index 8a382514a6121..a2681b098a2fc 100644 --- a/packages/grafana-schema/src/raw/composable/gauge/panelcfg/x/GaugePanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/gauge/panelcfg/x/GaugePanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options extends common.SingleStatBaseOptions { minVizHeight: number; diff --git a/packages/grafana-schema/src/raw/composable/geomap/panelcfg/x/GeomapPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/geomap/panelcfg/x/GeomapPanelCfg_types.gen.ts index 1bc6083306716..cd182447349e2 100644 --- a/packages/grafana-schema/src/raw/composable/geomap/panelcfg/x/GeomapPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/geomap/panelcfg/x/GeomapPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as ui from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options { basemap: ui.MapLayerOptions; diff --git a/packages/grafana-schema/src/raw/composable/heatmap/panelcfg/x/HeatmapPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/heatmap/panelcfg/x/HeatmapPanelCfg_types.gen.ts index 7b75bdaf77643..61e1a431d2434 100644 --- a/packages/grafana-schema/src/raw/composable/heatmap/panelcfg/x/HeatmapPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/heatmap/panelcfg/x/HeatmapPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as ui from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; /** * Controls the color mode of the heatmap diff --git a/packages/grafana-schema/src/raw/composable/histogram/panelcfg/x/HistogramPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/histogram/panelcfg/x/HistogramPanelCfg_types.gen.ts index 710fd6eb28f1e..6a1c49699f9c6 100644 --- a/packages/grafana-schema/src/raw/composable/histogram/panelcfg/x/HistogramPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/histogram/panelcfg/x/HistogramPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options extends common.OptionsWithLegend, common.OptionsWithTooltip { /** diff --git a/packages/grafana-schema/src/raw/composable/logs/panelcfg/x/LogsPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/logs/panelcfg/x/LogsPanelCfg_types.gen.ts index e4e1c3eab1e3e..f0c1638d04550 100644 --- a/packages/grafana-schema/src/raw/composable/logs/panelcfg/x/LogsPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/logs/panelcfg/x/LogsPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options { dedupStrategy: common.LogsDedupStrategy; diff --git a/packages/grafana-schema/src/raw/composable/loki/dataquery/x/LokiDataQuery_types.gen.ts b/packages/grafana-schema/src/raw/composable/loki/dataquery/x/LokiDataQuery_types.gen.ts index 2abe444f4425f..d04040c1eb7be 100644 --- a/packages/grafana-schema/src/raw/composable/loki/dataquery/x/LokiDataQuery_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/loki/dataquery/x/LokiDataQuery_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export enum QueryEditorMode { Builder = 'builder', diff --git a/packages/grafana-schema/src/raw/composable/news/panelcfg/x/NewsPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/news/panelcfg/x/NewsPanelCfg_types.gen.ts index 7d0b13b6c3399..6e2932159faf6 100644 --- a/packages/grafana-schema/src/raw/composable/news/panelcfg/x/NewsPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/news/panelcfg/x/NewsPanelCfg_types.gen.ts @@ -8,7 +8,7 @@ // // Run 'make gen-cue' from repository root to regenerate. -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options { /** diff --git a/packages/grafana-schema/src/raw/composable/nodegraph/panelcfg/x/NodeGraphPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/nodegraph/panelcfg/x/NodeGraphPanelCfg_types.gen.ts index 2890cf80897fd..d970bc30fa244 100644 --- a/packages/grafana-schema/src/raw/composable/nodegraph/panelcfg/x/NodeGraphPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/nodegraph/panelcfg/x/NodeGraphPanelCfg_types.gen.ts @@ -8,7 +8,7 @@ // // Run 'make gen-cue' from repository root to regenerate. -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface ArcOption { /** diff --git a/packages/grafana-schema/src/raw/composable/piechart/panelcfg/x/PieChartPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/piechart/panelcfg/x/PieChartPanelCfg_types.gen.ts index 0bd6aab432c4c..ea73ebd345aa1 100644 --- a/packages/grafana-schema/src/raw/composable/piechart/panelcfg/x/PieChartPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/piechart/panelcfg/x/PieChartPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; /** * Select the pie chart display style. diff --git a/packages/grafana-schema/src/raw/composable/stat/panelcfg/x/StatPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/stat/panelcfg/x/StatPanelCfg_types.gen.ts index b71651776d918..bb96ca0c7709e 100644 --- a/packages/grafana-schema/src/raw/composable/stat/panelcfg/x/StatPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/stat/panelcfg/x/StatPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options extends common.SingleStatBaseOptions { colorMode: common.BigValueColorMode; diff --git a/packages/grafana-schema/src/raw/composable/statetimeline/panelcfg/x/StateTimelinePanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/statetimeline/panelcfg/x/StateTimelinePanelCfg_types.gen.ts index b8f59503bc68c..ae0e3f3c56289 100644 --- a/packages/grafana-schema/src/raw/composable/statetimeline/panelcfg/x/StateTimelinePanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/statetimeline/panelcfg/x/StateTimelinePanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as ui from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options extends ui.OptionsWithLegend, ui.OptionsWithTooltip, ui.OptionsWithTimezones { /** diff --git a/packages/grafana-schema/src/raw/composable/statushistory/panelcfg/x/StatusHistoryPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/statushistory/panelcfg/x/StatusHistoryPanelCfg_types.gen.ts index 166363cd02c2d..a8856152eab0c 100644 --- a/packages/grafana-schema/src/raw/composable/statushistory/panelcfg/x/StatusHistoryPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/statushistory/panelcfg/x/StatusHistoryPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as ui from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options extends ui.OptionsWithLegend, ui.OptionsWithTooltip, ui.OptionsWithTimezones { /** diff --git a/packages/grafana-schema/src/raw/composable/table/panelcfg/x/TablePanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/table/panelcfg/x/TablePanelCfg_types.gen.ts index 7015f91f9ed2f..6259a31b663ec 100644 --- a/packages/grafana-schema/src/raw/composable/table/panelcfg/x/TablePanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/table/panelcfg/x/TablePanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as ui from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options { /** diff --git a/packages/grafana-schema/src/raw/composable/text/panelcfg/x/TextPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/text/panelcfg/x/TextPanelCfg_types.gen.ts index 1f90296463d9e..3b97984f81cb6 100644 --- a/packages/grafana-schema/src/raw/composable/text/panelcfg/x/TextPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/text/panelcfg/x/TextPanelCfg_types.gen.ts @@ -8,7 +8,7 @@ // // Run 'make gen-cue' from repository root to regenerate. -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export enum TextMode { Code = 'code', diff --git a/packages/grafana-schema/src/raw/composable/timeseries/panelcfg/x/TimeSeriesPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/timeseries/panelcfg/x/TimeSeriesPanelCfg_types.gen.ts index 3ce9e2f60a5c6..d7dc9c8d9cabc 100644 --- a/packages/grafana-schema/src/raw/composable/timeseries/panelcfg/x/TimeSeriesPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/timeseries/panelcfg/x/TimeSeriesPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; export interface Options extends common.OptionsWithTimezones { legend: common.VizLegendOptions; diff --git a/packages/grafana-schema/src/raw/composable/trend/panelcfg/x/TrendPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/trend/panelcfg/x/TrendPanelCfg_types.gen.ts index 94790b238d7b7..4b665ec5dcd66 100644 --- a/packages/grafana-schema/src/raw/composable/trend/panelcfg/x/TrendPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/trend/panelcfg/x/TrendPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; /** * Identical to timeseries... except it does not have timezone settings diff --git a/packages/grafana-schema/src/raw/composable/xychart/panelcfg/x/XYChartPanelCfg_types.gen.ts b/packages/grafana-schema/src/raw/composable/xychart/panelcfg/x/XYChartPanelCfg_types.gen.ts index 3844ff6847436..6afc97b5f4281 100644 --- a/packages/grafana-schema/src/raw/composable/xychart/panelcfg/x/XYChartPanelCfg_types.gen.ts +++ b/packages/grafana-schema/src/raw/composable/xychart/panelcfg/x/XYChartPanelCfg_types.gen.ts @@ -10,7 +10,7 @@ import * as common from '@grafana/schema'; -export const pluginVersion = "11.1.4"; +export const pluginVersion = ""; /** * Auto is "table" in the UI diff --git a/packages/grafana-sql/package.json b/packages/grafana-sql/package.json index 28c0b8eb46d23..65dfdac4bb7a5 100644 --- a/packages/grafana-sql/package.json +++ b/packages/grafana-sql/package.json @@ -3,7 +3,7 @@ "license": "AGPL-3.0-only", "private": true, "name": "@grafana/sql", - "version": "11.1.4", + "version": "11.1.5", "repository": { "type": "git", "url": "http://github.com/grafana/grafana.git", @@ -15,11 +15,11 @@ }, "dependencies": { "@emotion/css": "11.11.2", - "@grafana/data": "11.1.4", - "@grafana/e2e-selectors": "11.1.4", + "@grafana/data": "11.1.5", + "@grafana/e2e-selectors": "11.1.5", "@grafana/experimental": "1.7.11", - "@grafana/runtime": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/runtime": "11.1.5", + "@grafana/ui": "11.1.5", "@react-awesome-query-builder/ui": "6.5.2", "immutable": "4.3.6", "lodash": "4.17.21", diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 577978954c53e..80c99598c465e 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/ui", - "version": "11.1.4", + "version": "11.1.5", "description": "Grafana Components Library", "keywords": [ "grafana", @@ -50,10 +50,10 @@ "@emotion/css": "11.11.2", "@emotion/react": "11.11.4", "@floating-ui/react": "0.26.16", - "@grafana/data": "11.1.4", - "@grafana/e2e-selectors": "11.1.4", + "@grafana/data": "11.1.5", + "@grafana/e2e-selectors": "11.1.5", "@grafana/faro-web-sdk": "^1.3.6", - "@grafana/schema": "11.1.4", + "@grafana/schema": "11.1.5", "@leeoniya/ufuzzy": "1.0.14", "@monaco-editor/react": "4.6.0", "@popperjs/core": "2.11.8", diff --git a/packages/grafana-ui/src/components/Table/utils.ts b/packages/grafana-ui/src/components/Table/utils.ts index 940734cbd2f09..bbd6c66cc1372 100644 --- a/packages/grafana-ui/src/components/Table/utils.ts +++ b/packages/grafana-ui/src/components/Table/utils.ts @@ -645,7 +645,7 @@ export function guessTextBoundingBox( lineHeight: number, defaultRowHeight: number ) { - const width = Number(headerGroup.width ?? 300); + const width = Number(headerGroup?.width ?? 300); const LINE_SCALE_FACTOR = 1.17; const LOW_LINE_PAD = 42; diff --git a/packages/grafana-ui/src/components/Typeahead/Typeahead.tsx b/packages/grafana-ui/src/components/Typeahead/Typeahead.tsx index c1365403da672..37efc58467ea3 100644 --- a/packages/grafana-ui/src/components/Typeahead/Typeahead.tsx +++ b/packages/grafana-ui/src/components/Typeahead/Typeahead.tsx @@ -220,7 +220,7 @@ class Portal extends PureComponent, {}> { const { index = 0, origin = 'query', style } = props; this.node = document.createElement('div'); this.node.setAttribute('style', style); - this.node.classList.add(`slate-typeahead`, `slate-typeahead-${origin}-${index}`); + this.node.classList.add(`slate-typeahead-${origin}-${index}`); document.body.appendChild(this.node); } @@ -243,8 +243,18 @@ class Portal extends PureComponent, {}> { const getStyles = (theme: GrafanaTheme2) => ({ typeahead: css({ - maxHeight: 300, - overflowY: 'auto', + position: 'relative', + zIndex: theme.zIndex.typeahead, + borderRadius: theme.shape.radius.default, + border: `1px solid ${theme.components.panel.borderColor}`, + maxHeight: '66vh', + overflowY: 'scroll', + overflowX: 'hidden', + outline: 'none', + listStyle: 'none', + background: theme.components.panel.background, + color: theme.colors.text.primary, + boxShadow: theme.shadows.z2, strong: { color: theme.v1.palette.yellow, diff --git a/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx b/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx index f08e075a8acf3..956b634cd577e 100644 --- a/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx +++ b/packages/grafana-ui/src/components/VizTooltip/VizTooltipRow.tsx @@ -47,7 +47,7 @@ export const VizTooltipRow = ({ maxHeight: 55, whiteSpace: 'wrap', wordBreak: 'break-word', - overflowY: 'scroll', + overflowY: 'auto', } : { whiteSpace: 'wrap', diff --git a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx index bc40f0506ba5b..8702a784a9a2f 100644 --- a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx +++ b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx @@ -312,8 +312,10 @@ export const TooltipPlugin2 = ({ } // only pinnable tooltip is visible *and* is within proximity to series/point else if (_isHovering && closestSeriesIdx != null && !_isPinned) { - _isPinned = true; - scheduleRender(true); + setTimeout(() => { + _isPinned = true; + scheduleRender(true); + }, 0); } } }); @@ -604,14 +606,29 @@ export const TooltipPlugin2 = ({ size.width = width; size.height = height; - const event = plot!.cursor.event; + let event = plot!.cursor.event; // if not viaSync, re-dispatch real event if (event != null) { + // we expect to re-dispatch mousemove, but on mobile we'll get mouseup or click + const isMobile = event.type !== 'mousemove'; + + if (isMobile) { + event = new MouseEvent('mousemove', { + view: window, + bubbles: true, + cancelable: true, + clientX: event.clientX, + clientY: event.clientY, + screenX: event.screenX, + screenY: event.screenY, + }); + } + // this works around the fact that uPlot does not unset cursor.event (for perf reasons) // so if the last real mouse event was mouseleave and you manually trigger u.setCursor() // it would end up re-dispatching mouseleave - const isStaleEvent = performance.now() - event.timeStamp > 16; + const isStaleEvent = isMobile ? false : performance.now() - event.timeStamp > 16; !isStaleEvent && plot!.over.dispatchEvent(event); } else { diff --git a/pkg/services/accesscontrol/authorize_in_org_test.go b/pkg/services/accesscontrol/authorize_in_org_test.go index f9cc616c73a95..b9bd6235b4fde 100644 --- a/pkg/services/accesscontrol/authorize_in_org_test.go +++ b/pkg/services/accesscontrol/authorize_in_org_test.go @@ -1,7 +1,6 @@ package accesscontrol_test import ( - "context" "fmt" "net/http" "net/http/httptest" @@ -11,7 +10,7 @@ import ( "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/acimpl" - "github.com/grafana/grafana/pkg/services/accesscontrol/actest" + "github.com/grafana/grafana/pkg/services/auth/identity" "github.com/grafana/grafana/pkg/services/authn" "github.com/grafana/grafana/pkg/services/authn/authntest" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" @@ -19,7 +18,6 @@ import ( "github.com/grafana/grafana/pkg/services/team" "github.com/grafana/grafana/pkg/services/team/teamtest" "github.com/grafana/grafana/pkg/services/user" - "github.com/grafana/grafana/pkg/services/user/usertest" "github.com/grafana/grafana/pkg/web" ) @@ -34,8 +32,8 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { orgIDGetter accesscontrol.OrgIDGetter evaluator accesscontrol.Evaluator accessControl accesscontrol.AccessControl - acService accesscontrol.Service - userCache user.Service + userIdentities []*authn.Identity + authnErrors []error ctxSignedInUser *user.SignedInUser teamService team.Service expectedStatus int @@ -45,7 +43,6 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { targetOrgId: accesscontrol.GlobalOrgID, evaluator: accesscontrol.EvalPermission("users:read", "users:*"), accessControl: ac, - userCache: &usertest.FakeUserService{}, ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, targerOrgPermissions: []accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}}, teamService: &teamtest.FakeService{}, @@ -57,7 +54,6 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { targerOrgPermissions: []accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}}, evaluator: accesscontrol.EvalPermission("users:read", "users:*"), accessControl: ac, - userCache: &usertest.FakeUserService{}, ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, teamService: &teamtest.FakeService{}, expectedStatus: http.StatusOK, @@ -68,7 +64,6 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { targerOrgPermissions: []accesscontrol.Permission{}, evaluator: accesscontrol.EvalPermission("users:read", "users:*"), accessControl: ac, - userCache: &usertest.FakeUserService{}, ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{}}, teamService: &teamtest.FakeService{}, expectedStatus: http.StatusForbidden, @@ -79,7 +74,6 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { targerOrgPermissions: []accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}}, evaluator: accesscontrol.EvalPermission("users:read", "users:*"), accessControl: ac, - userCache: &usertest.FakeUserService{}, ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, teamService: &teamtest.FakeService{}, expectedStatus: http.StatusOK, @@ -90,33 +84,10 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { targerOrgPermissions: []accesscontrol.Permission{}, evaluator: accesscontrol.EvalPermission("users:read", "users:*"), accessControl: ac, - userCache: &usertest.FakeUserService{}, ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, teamService: &teamtest.FakeService{}, expectedStatus: http.StatusForbidden, }, - { - name: "should return 403 when user org ID doesn't match and user does not exist in org 2", - targetOrgId: 2, - targerOrgPermissions: []accesscontrol.Permission{}, - evaluator: accesscontrol.EvalPermission("users:read", "users:*"), - accessControl: ac, - userCache: &usertest.FakeUserService{ExpectedError: fmt.Errorf("user not found")}, - ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, - teamService: &teamtest.FakeService{}, - expectedStatus: http.StatusForbidden, - }, - { - name: "should return 403 early when api key org ID doesn't match", - targetOrgId: 2, - targerOrgPermissions: []accesscontrol.Permission{}, - evaluator: accesscontrol.EvalPermission("users:read", "users:*"), - accessControl: ac, - userCache: &usertest.FakeUserService{}, - ctxSignedInUser: &user.SignedInUser{ApiKeyID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, - teamService: &teamtest.FakeService{}, - expectedStatus: http.StatusForbidden, - }, { name: "should fetch user permissions when org ID doesn't match", targetOrgId: 2, @@ -124,13 +95,8 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { evaluator: accesscontrol.EvalPermission("users:read", "users:*"), accessControl: ac, teamService: &teamtest.FakeService{}, - userCache: &usertest.FakeUserService{ - GetSignedInUserFn: func(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) { - return &user.SignedInUser{UserID: 1, OrgID: 2, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, nil - }, - }, - ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:write": {"users:*"}}}}, - expectedStatus: http.StatusOK, + ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:write": {"users:*"}}}}, + expectedStatus: http.StatusOK, }, { name: "fails to fetch user permissions when org ID doesn't match", @@ -139,16 +105,9 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { evaluator: accesscontrol.EvalPermission("users:read", "users:*"), accessControl: ac, teamService: &teamtest.FakeService{}, - acService: &actest.FakeService{ - ExpectedErr: fmt.Errorf("failed to get user permissions"), - }, - userCache: &usertest.FakeUserService{ - GetSignedInUserFn: func(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) { - return &user.SignedInUser{UserID: 1, OrgID: 2, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, nil - }, - }, - ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, - expectedStatus: http.StatusForbidden, + authnErrors: []error{fmt.Errorf("failed to get user permissions")}, + ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, + expectedStatus: http.StatusForbidden, }, { name: "unable to get target org", @@ -157,24 +116,35 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { }, evaluator: accesscontrol.EvalPermission("users:read", "users:*"), accessControl: ac, - userCache: &usertest.FakeUserService{}, ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, teamService: &teamtest.FakeService{}, expectedStatus: http.StatusForbidden, }, { - name: "should fetch global user permissions when user is not a member of the target org", - targetOrgId: 2, - targerOrgPermissions: []accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}}, - evaluator: accesscontrol.EvalPermission("users:read", "users:*"), - accessControl: ac, - userCache: &usertest.FakeUserService{ - GetSignedInUserFn: func(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) { - return &user.SignedInUser{UserID: 1, OrgID: -1, Permissions: map[int64]map[string][]string{}}, nil - }, + name: "should fetch global user permissions when user is not a member of the target org", + targetOrgId: 2, + evaluator: accesscontrol.EvalPermission("users:read", "users:*"), + accessControl: ac, + ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:write": {"users:*"}}}}, + userIdentities: []*authn.Identity{ + {ID: identity.MustParseNamespaceID("user:1"), OrgID: -1, Permissions: map[int64]map[string][]string{}}, + {ID: identity.MustParseNamespaceID("user:1"), OrgID: accesscontrol.GlobalOrgID, Permissions: map[int64]map[string][]string{accesscontrol.GlobalOrgID: {"users:read": {"users:*"}}}}, }, + authnErrors: []error{nil, nil}, + expectedStatus: http.StatusOK, + }, + { + name: "should fail if user is not a member of the target org and doesn't have the right permissions globally", + targetOrgId: 2, + evaluator: accesscontrol.EvalPermission("users:read", "users:*"), + accessControl: ac, ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:write": {"users:*"}}}}, - expectedStatus: http.StatusOK, + userIdentities: []*authn.Identity{ + {ID: identity.MustParseNamespaceID("user:1"), OrgID: -1, Permissions: map[int64]map[string][]string{}}, + {ID: identity.MustParseNamespaceID("user:1"), OrgID: accesscontrol.GlobalOrgID, Permissions: map[int64]map[string][]string{accesscontrol.GlobalOrgID: {"folders:read": {"folders:*"}}}}, + }, + authnErrors: []error{nil, nil}, + expectedStatus: http.StatusForbidden, }, } @@ -190,9 +160,16 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { Permissions: map[int64]map[string][]string{}, } expectedIdentity.Permissions[tc.targetOrgId] = accesscontrol.GroupScopesByAction(tc.targerOrgPermissions) + var expectedErr error + if len(tc.authnErrors) > 0 { + expectedErr = tc.authnErrors[0] + } authnService := &authntest.FakeService{ - ExpectedIdentity: expectedIdentity, + ExpectedIdentity: expectedIdentity, + ExpectedIdentities: tc.userIdentities, + ExpectedErr: expectedErr, + ExpectedErrs: tc.authnErrors, } var orgIDGetter accesscontrol.OrgIDGetter diff --git a/pkg/services/accesscontrol/middleware.go b/pkg/services/accesscontrol/middleware.go index 714f37b90417e..6cb77dd454c5f 100644 --- a/pkg/services/accesscontrol/middleware.go +++ b/pkg/services/accesscontrol/middleware.go @@ -195,6 +195,10 @@ func AuthorizeInOrgMiddleware(ac AccessControl, authnService authn.Service) func var orgUser identity.Requester = c.SignedInUser if targetOrgID != c.SignedInUser.GetOrgID() { orgUser, err = authnService.ResolveIdentity(c.Req.Context(), targetOrgID, c.SignedInUser.GetID()) + if err == nil && orgUser.GetOrgID() == NoOrgID { + // User is not a member of the target org, so only their global permissions are relevant + orgUser, err = authnService.ResolveIdentity(c.Req.Context(), GlobalOrgID, c.SignedInUser.GetID()) + } if err != nil { deny(c, nil, fmt.Errorf("failed to authenticate user in target org: %w", err)) return diff --git a/pkg/services/dashboardsnapshots/database/database.go b/pkg/services/dashboardsnapshots/database/database.go index f3e32c2393435..15ac70a131003 100644 --- a/pkg/services/dashboardsnapshots/database/database.go +++ b/pkg/services/dashboardsnapshots/database/database.go @@ -34,7 +34,7 @@ func NewStore(db db.DB, skipDeleteExpired bool) *DashboardSnapshotStore { if skipDeleteExpired { log.Warn("[Deprecated] The snapshot_remove_expired setting is outdated. Please remove from your config.") } - return &DashboardSnapshotStore{store: db, skipDeleteExpired: skipDeleteExpired} + return &DashboardSnapshotStore{store: db, skipDeleteExpired: skipDeleteExpired, log: log} } // DeleteExpiredSnapshots removes snapshots with old expiry dates. diff --git a/pkg/services/ngalert/state/cache.go b/pkg/services/ngalert/state/cache.go index ae82381310eed..b6f2c412a5d0f 100644 --- a/pkg/services/ngalert/state/cache.go +++ b/pkg/services/ngalert/state/cache.go @@ -92,10 +92,10 @@ func (c *cache) getOrCreate(ctx context.Context, log log.Logger, alertRule *ngMo states = &ruleStates{states: make(map[string]*State)} c.states[stateCandidate.OrgID][stateCandidate.AlertRuleUID] = states } - return states.getOrAdd(stateCandidate) + return states.getOrAdd(stateCandidate, log) } -func (rs *ruleStates) getOrAdd(stateCandidate State) *State { +func (rs *ruleStates) getOrAdd(stateCandidate State, log log.Logger) *State { state, ok := rs.states[stateCandidate.CacheID] // Check if the state with this ID already exists. if !ok { @@ -116,6 +116,10 @@ func (rs *ruleStates) getOrAdd(stateCandidate State) *State { } state.Annotations = stateCandidate.Annotations state.Values = stateCandidate.Values + if state.ResultFingerprint != stateCandidate.ResultFingerprint { + log.Info("Result fingerprint has changed", "oldFingerprint", state.ResultFingerprint, "newFingerprint", stateCandidate.ResultFingerprint, "cacheID", state.CacheID, "stateLabels", state.Labels.String()) + state.ResultFingerprint = stateCandidate.ResultFingerprint + } rs.states[stateCandidate.CacheID] = state return state } diff --git a/pkg/services/ngalert/state/persister_sync.go b/pkg/services/ngalert/state/persister_sync.go index bc8c5cf16736a..019f86fd6aa61 100644 --- a/pkg/services/ngalert/state/persister_sync.go +++ b/pkg/services/ngalert/state/persister_sync.go @@ -93,6 +93,7 @@ func (a *SyncStatePersister) saveAlertStates(ctx context.Context, states ...Stat LastEvalTime: s.LastEvaluationTime, CurrentStateSince: s.StartsAt, CurrentStateEnd: s.EndsAt, + ResultFingerprint: s.ResultFingerprint.String(), } err = a.store.SaveAlertInstance(ctx, instance) diff --git a/pkg/services/ngalert/state/persister_sync_test.go b/pkg/services/ngalert/state/persister_sync_test.go index 4465cebdb1e1e..f65394e410c08 100644 --- a/pkg/services/ngalert/state/persister_sync_test.go +++ b/pkg/services/ngalert/state/persister_sync_test.go @@ -2,9 +2,13 @@ package state import ( "context" + "errors" "fmt" + "math/rand" "testing" + "time" + "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "k8s.io/component-base/tracing" @@ -100,4 +104,75 @@ func TestSyncPersister_saveAlertStates(t *testing.T) { assert.Containsf(t, savedKeys, key, "state %s (%s) was not saved but should be", tr.State.State, tr.StateReason) } }) + + t.Run("should save expected fields", func(t *testing.T) { + trace := tracing.NewNoopTracerProvider().Tracer("test") + _, span := trace.Start(context.Background(), "") + st := &FakeInstanceStore{} + syncStatePersister := NewSyncStatePersisiter(&logtest.Fake{}, ManagerCfg{ + InstanceStore: st, + MaxStateSaveConcurrency: 1, + }) + + state := &State{ + OrgID: rand.Int63(), + AlertRuleUID: util.GenerateShortUID(), + CacheID: data.Fingerprint(rand.Int63()).String(), + State: eval.Alerting, + StateReason: "TEST", + ResultFingerprint: data.Fingerprint(rand.Int63()), + LatestResult: &Evaluation{ + EvaluationTime: time.Now().Add(1 * time.Minute), + EvaluationState: eval.Alerting, + Values: map[string]*float64{ + "A": util.Pointer(1.0), + "B": util.Pointer(2.0), + }, + Condition: "A", + }, + Error: errors.New("test"), + Image: &ngmodels.Image{ + ID: rand.Int63(), + Token: util.GenerateShortUID(), + Path: util.GenerateShortUID(), + URL: util.GenerateShortUID(), + CreatedAt: time.Now().Add(2 * time.Minute), + ExpiresAt: time.Now().Add(3 * time.Minute), + }, + Annotations: ngmodels.GenerateAlertLabels(4, "annotations_"), + Labels: ngmodels.GenerateAlertLabels(4, "labels_"), + Values: map[string]float64{ + "A1": 11.0, + "B1": 12.0, + }, + StartsAt: time.Now().Add(4 * time.Minute), + EndsAt: time.Now().Add(5 * time.Minute), + LastSentAt: time.Now().Add(7 * time.Minute), + LastEvaluationString: util.GenerateShortUID(), + LastEvaluationTime: time.Now().Add(8 * time.Minute), + EvaluationDuration: time.Duration(rand.Intn(100)+1) * time.Second, + } + + transition := StateTransition{ + State: state, + PreviousState: eval.Normal, + PreviousStateReason: util.GenerateShortUID(), + } + + syncStatePersister.Sync(context.Background(), span, []StateTransition{transition}, nil) + + require.Len(t, st.RecordedOps(), 1) + saved := st.RecordedOps()[0].(ngmodels.AlertInstance) + + expectedAlertInstanceKey, err := state.GetAlertInstanceKey() + require.NoError(t, err) + assert.Equal(t, expectedAlertInstanceKey, saved.AlertInstanceKey) + assert.Equal(t, ngmodels.InstanceLabels(state.Labels), saved.Labels) + assert.EqualValues(t, ngmodels.InstanceStateType(state.State.String()), saved.CurrentState) + assert.Equal(t, state.StateReason, saved.CurrentReason) + assert.Equal(t, state.StartsAt, saved.CurrentStateSince) + assert.Equal(t, state.EndsAt, saved.CurrentStateEnd) + assert.Equal(t, state.LastEvaluationTime, saved.LastEvalTime) + assert.Equal(t, state.ResultFingerprint.String(), saved.ResultFingerprint) + }) } diff --git a/pkg/tsdb/opentsdb/opentsdb.go b/pkg/tsdb/opentsdb/opentsdb.go index 5d1902c7ac947..15a1fe270466d 100644 --- a/pkg/tsdb/opentsdb/opentsdb.go +++ b/pkg/tsdb/opentsdb/opentsdb.go @@ -8,7 +8,6 @@ import ( "net/http" "net/url" "path" - "strconv" "strings" "time" @@ -121,6 +120,9 @@ func (s *Service) createRequest(ctx context.Context, logger log.Logger, dsInfo * return nil, err } u.Path = path.Join(u.Path, "api/query") + queryParams := u.Query() + queryParams.Set("arrays", "true") + u.RawQuery = queryParams.Encode() postData, err := json.Marshal(data) if err != nil { @@ -165,23 +167,25 @@ func (s *Service) parseResponse(logger log.Logger, res *http.Response, myRefID s frames := data.Frames{} for _, val := range responseData { - timeVector := make([]time.Time, 0, len(val.DataPoints)) - values := make([]float64, 0, len(val.DataPoints)) - name := val.Metric - tags := val.Tags - - for timeString, value := range val.DataPoints { - timestamp, err := strconv.ParseInt(timeString, 10, 64) - if err != nil { - logger.Info("Failed to unmarshal opentsdb timestamp", "timestamp", timeString) - return nil, err - } - timeVector = append(timeVector, time.Unix(timestamp, 0).UTC()) - values = append(values, value) + labels := data.Labels{} + for label, value := range val.Tags { + labels[label] = value } - frames = append(frames, data.NewFrame(name, - data.NewField("time", nil, timeVector), - data.NewField("value", tags, values))) + + frame := data.NewFrameOfFieldTypes(val.Metric, len(val.DataPoints), data.FieldTypeTime, data.FieldTypeFloat64) + frame.Meta = &data.FrameMeta{Type: data.FrameTypeTimeSeriesMulti, TypeVersion: data.FrameTypeVersion{0, 1}} + frame.RefID = myRefID + timeField := frame.Fields[0] + timeField.Name = data.TimeSeriesTimeFieldName + dataField := frame.Fields[1] + dataField.Name = "value" + dataField.Labels = labels + + points := val.DataPoints + for i, point := range points { + frame.SetRow(i, time.Unix(int64(point[0]), 0).UTC(), point[1]) + } + frames = append(frames, frame) } result := resp.Responses[myRefID] result.Frames = frames diff --git a/pkg/tsdb/opentsdb/opentsdb_test.go b/pkg/tsdb/opentsdb/opentsdb_test.go index a48c14188f4ab..6c5e142c250c5 100644 --- a/pkg/tsdb/opentsdb/opentsdb_test.go +++ b/pkg/tsdb/opentsdb/opentsdb_test.go @@ -43,9 +43,9 @@ func TestOpenTsdbExecutor(t *testing.T) { [ { "metric": "test", - "dps": { - "1405544146": 50.0 - }, + "dps": [ + [1405544146, 50.0] + ], "tags" : { "env": "prod", "app": "grafana" @@ -54,12 +54,17 @@ func TestOpenTsdbExecutor(t *testing.T) { ]` testFrame := data.NewFrame("test", - data.NewField("time", nil, []time.Time{ + data.NewField("Time", nil, []time.Time{ time.Date(2014, 7, 16, 20, 55, 46, 0, time.UTC), }), data.NewField("value", map[string]string{"env": "prod", "app": "grafana"}, []float64{ 50}), ) + testFrame.Meta = &data.FrameMeta{ + Type: data.FrameTypeTimeSeriesMulti, + TypeVersion: data.FrameTypeVersion{0, 1}, + } + testFrame.RefID = "A" resp := http.Response{Body: io.NopCloser(strings.NewReader(response))} resp.StatusCode = 200 @@ -80,9 +85,9 @@ func TestOpenTsdbExecutor(t *testing.T) { [ { "metric": "test", - "dps": { - "1405544146": 50.0 - }, + "dps": [ + [1405544146, 50.0] + ], "tags" : { "env": "prod", "app": "grafana" @@ -91,12 +96,17 @@ func TestOpenTsdbExecutor(t *testing.T) { ]` testFrame := data.NewFrame("test", - data.NewField("time", nil, []time.Time{ + data.NewField("Time", nil, []time.Time{ time.Date(2014, 7, 16, 20, 55, 46, 0, time.UTC), }), data.NewField("value", map[string]string{"env": "prod", "app": "grafana"}, []float64{ 50}), ) + testFrame.Meta = &data.FrameMeta{ + Type: data.FrameTypeTimeSeriesMulti, + TypeVersion: data.FrameTypeVersion{0, 1}, + } + testFrame.RefID = myRefid resp := http.Response{Body: io.NopCloser(strings.NewReader(response))} resp.StatusCode = 200 diff --git a/pkg/tsdb/opentsdb/types.go b/pkg/tsdb/opentsdb/types.go index 96c43ead02d0e..171a24e20670a 100644 --- a/pkg/tsdb/opentsdb/types.go +++ b/pkg/tsdb/opentsdb/types.go @@ -7,7 +7,7 @@ type OpenTsdbQuery struct { } type OpenTsdbResponse struct { - Metric string `json:"metric"` - Tags map[string]string `json:"tags"` - DataPoints map[string]float64 `json:"dps"` + Metric string `json:"metric"` + Tags map[string]string `json:"tags"` + DataPoints [][]float64 `json:"dps"` } diff --git a/public/app/core/components/GraphNG/GraphNG.tsx b/public/app/core/components/GraphNG/GraphNG.tsx index f2575110289b6..44616c2b03bc0 100644 --- a/public/app/core/components/GraphNG/GraphNG.tsx +++ b/public/app/core/components/GraphNG/GraphNG.tsx @@ -131,25 +131,36 @@ export class GraphNG extends Component { if (withLinks) { const timeZone = Array.isArray(this.props.timeZone) ? this.props.timeZone[0] : this.props.timeZone; - alignedFrame.fields.forEach((field) => { - field.getLinks = getLinksSupplier( - alignedFrame, - field, - { - ...field.state?.scopedVars, - __dataContext: { - value: { - data: [alignedFrame], - field: field, - frame: alignedFrame, - frameIndex: 0, + // for links gen we need to use original frames but with the aligned/joined data values + let linkFrames = frames.map((frame, frameIdx) => ({ + ...frame, + fields: alignedFrame.fields.filter( + (field, fieldIdx) => fieldIdx === 0 || field.state?.origin?.frameIndex === frameIdx + ), + length: alignedFrame.length, + })); + + linkFrames.forEach((linkFrame, frameIndex) => { + linkFrame.fields.forEach((field) => { + field.getLinks = getLinksSupplier( + linkFrame, + field, + { + ...field.state?.scopedVars, + __dataContext: { + value: { + data: linkFrames, + field: field, + frame: linkFrame, + frameIndex, + }, }, }, - }, - replaceVariables, - timeZone, - dataLinkPostProcessor - ); + replaceVariables, + timeZone, + dataLinkPostProcessor + ); + }); }); // filter join field and fields.y diff --git a/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.test.tsx b/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.test.tsx index 5e916d86781e9..2820bc3b2e80e 100644 --- a/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.test.tsx +++ b/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.test.tsx @@ -1,6 +1,5 @@ -import { render } from '@testing-library/react'; import React from 'react'; -import { Provider } from 'react-redux'; +import { render, screen, userEvent } from 'test/test-utils'; import { byLabelText, byTestId, byText, byTitle } from 'testing-library-selector'; import { CombinedRuleNamespace } from 'app/types/unified-alerting'; @@ -13,8 +12,6 @@ import { mockPromRecordingRule, mockRulerAlertingRule, mockRulerRecordingRule, - mockRulerRuleGroup, - mockStore, } from '../../mocks'; import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource'; @@ -31,29 +28,8 @@ const ui = { tableRows: byTestId('row'), noRulesText: byText('This group does not contain alert rules.'), }; -mockRulerRuleGroup({ - name: 'group1', - rules: [ - mockRulerRecordingRule({ - record: 'instance:node_num_cpu:sum', - expr: 'count without (cpu) (count without (mode) (node_cpu_seconds_total{job="integrations/node_exporter"}))', - labels: { type: 'cpu' }, - }), - mockRulerAlertingRule({ alert: 'nonRecordingRule' }), - ], -}); - -jest.mock('app/types', () => ({ - ...jest.requireActual('app/types'), - useDispatch: () => jest.fn(), -})); -function getProvidersWrapper() { - return function Wrapper({ children }: React.PropsWithChildren<{}>) { - const store = mockStore(() => null); - return {children}; - }; -} +const noop = () => jest.fn(); describe('EditGroupModal', () => { it('Should disable all inputs but interval when intervalEditOnly is set', async () => { @@ -65,9 +41,7 @@ describe('EditGroupModal', () => { const group = namespace.groups[0]; - render( jest.fn()} />, { - wrapper: getProvidersWrapper(), - }); + render(); expect(await ui.input.namespace.find()).toHaveAttribute('readonly'); expect(ui.input.group.get()).toHaveAttribute('readonly'); @@ -107,9 +81,7 @@ describe('EditGroupModal component on cloud alert rules', () => { const group = promNs.groups[0]; - render( jest.fn()} />, { - wrapper: getProvidersWrapper(), - }); + render(); expect(await ui.input.namespace.find()).toHaveValue('prometheus-ns'); expect(ui.input.namespace.get()).not.toHaveAttribute('readonly'); @@ -128,9 +100,7 @@ describe('EditGroupModal component on cloud alert rules', () => { const group = promNs.groups[0]; - render(, { - wrapper: getProvidersWrapper(), - }); + render(); expect(ui.table.query()).not.toBeInTheDocument(); expect(await ui.noRulesText.find()).toBeInTheDocument(); }); @@ -163,10 +133,11 @@ describe('EditGroupModal component on grafana-managed alert rules', () => { const grafanaGroup1 = grafanaNamespace.groups[0]; + const renderWithGrafanaGroup = () => + render(); + it('Should show alert table', async () => { - render(, { - wrapper: getProvidersWrapper(), - }); + renderWithGrafanaGroup(); expect(await ui.input.namespace.find()).toHaveValue('namespace1'); expect(ui.input.group.get()).toHaveValue('grafanaGroup1'); @@ -178,18 +149,22 @@ describe('EditGroupModal component on grafana-managed alert rules', () => { }); it('Should have folder input in readonly mode', async () => { - render(, { - wrapper: getProvidersWrapper(), - }); + renderWithGrafanaGroup(); expect(await ui.input.namespace.find()).toHaveAttribute('readonly'); }); it('Should not display folder link if no folderUrl provided', async () => { - render(, { - wrapper: getProvidersWrapper(), - }); + renderWithGrafanaGroup(); expect(await ui.input.namespace.find()).toHaveValue('namespace1'); expect(ui.folderLink.query()).not.toBeInTheDocument(); }); + + it('does not allow slashes in the group name', async () => { + const user = userEvent.setup(); + renderWithGrafanaGroup(); + await user.type(await ui.input.group.find(), 'group/with/slashes'); + await user.click(ui.input.interval.get()); + expect(await screen.findByText(/cannot contain \"\/\"/i)).toBeInTheDocument(); + }); }); diff --git a/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.tsx b/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.tsx index 662c582d1cd7d..13b0d8c46bc1c 100644 --- a/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.tsx +++ b/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.tsx @@ -24,6 +24,7 @@ import { EvaluationIntervalLimitExceeded } from '../InvalidIntervalWarning'; import { decodeGrafanaNamespace, encodeGrafanaNamespace } from '../expressions/util'; import { EvaluationGroupQuickPick } from '../rule-editor/EvaluationGroupQuickPick'; import { MIN_TIME_RANGE_STEP_S } from '../rule-editor/GrafanaEvaluationBehavior'; +import { checkForPathSeparator } from '../rule-editor/util'; const ITEMS_PER_PAGE = 10; @@ -278,6 +279,11 @@ export function EditCloudGroupModal(props: ModalProps): React.ReactElement { readOnly={intervalEditOnly || isGrafanaManagedGroup} {...register('namespaceName', { required: 'Namespace name is required.', + validate: { + // for Grafana-managed we do not validate the name of the folder because we use the UID anyway + pathSeparator: (namespaceName) => + isGrafanaManagedGroup ? true : checkForPathSeparator(namespaceName), + }, })} /> @@ -310,6 +316,9 @@ export function EditCloudGroupModal(props: ModalProps): React.ReactElement { readOnly={intervalEditOnly} {...register('groupName', { required: 'Evaluation group name is required.', + validate: { + pathSeparator: (namespace) => checkForPathSeparator(namespace), + }, })} /> diff --git a/public/app/features/dashboard-scene/scene/DashboardControls.tsx b/public/app/features/dashboard-scene/scene/DashboardControls.tsx index 5614c57bfd4ca..e47d048d8dcc6 100644 --- a/public/app/features/dashboard-scene/scene/DashboardControls.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardControls.tsx @@ -144,8 +144,7 @@ function getStyles(theme: GrafanaTheme2) { gap: theme.spacing(1), flexDirection: 'row', flexWrap: 'nowrap', - position: 'sticky', - top: 0, + position: 'relative', background: theme.colors.background.canvas, zIndex: theme.zIndex.activePanel, width: '100%', @@ -154,6 +153,10 @@ function getStyles(theme: GrafanaTheme2) { flexDirection: 'column-reverse', alignItems: 'stretch', }, + [theme.breakpoints.up('sm')]: { + position: 'sticky', + top: 0, + }, }), embedded: css({ background: 'unset', diff --git a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx index 28f75ecffdf58..cfb7d8ff713d1 100644 --- a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx @@ -1,11 +1,12 @@ import { css, cx } from '@emotion/css'; import React from 'react'; import { useLocation } from 'react-router-dom'; +import { useMedia } from 'react-use'; import { GrafanaTheme2, PageLayoutType } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { SceneComponentProps } from '@grafana/scenes'; -import { CustomScrollbar, useStyles2 } from '@grafana/ui'; +import { CustomScrollbar, useStyles2, useTheme2 } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { getNavModel } from 'app/core/selectors/navModel'; import DashboardEmpty from 'app/features/dashboard/dashgrid/DashboardEmpty'; @@ -63,18 +64,17 @@ export function DashboardSceneRenderer({ model }: SceneComponentProps )} -
<>{isEmpty && emptyState} {withPanels}
-
+ )} {overlay && } @@ -91,6 +91,10 @@ function getStyles(theme: GrafanaTheme2) { gridTemplateColumns: `1fr`, gridTemplateRows: '1fr', height: '100%', + [theme.breakpoints.down('sm')]: { + display: 'flex', + flexDirection: 'column', + }, }), pageContainerWithControls: css({ gridTemplateAreas: ` @@ -110,7 +114,7 @@ function getStyles(theme: GrafanaTheme2) { "scopes controls" "scopes panels"`, }), - scrollbarContainer: css({ + panelsContainer: css({ gridArea: 'panels', }), controlsWrapper: css({ @@ -147,3 +151,34 @@ function getStyles(theme: GrafanaTheme2) { }), }; } + +interface PanelsContainerProps { + id: string; + children: React.ReactNode; + className?: string; + testId?: string; +} +/** + * Removes the scrollbar on mobile and uses a custom scrollbar on desktop + */ +const PanelsContainer = ({ id, children, className, testId }: PanelsContainerProps) => { + const theme = useTheme2(); + const isMobile = useMedia(`(max-width: ${theme.breakpoints.values.sm}px)`); + const styles = useStyles2(() => ({ + nonScrollable: css({ + height: '100%', + display: 'flex', + flexDirection: 'column', + }), + })); + + return isMobile ? ( +
+ {children} +
+ ) : ( + + {children} + + ); +}; diff --git a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts index d20e8c0528661..e31b146b0de62 100644 --- a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts +++ b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts @@ -15,7 +15,14 @@ import { } from '@grafana/data'; import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks'; import { getPluginLinkExtensions, setPluginImportUtils } from '@grafana/runtime'; -import { MultiValueVariable, SceneGridLayout, SceneGridRow, SceneTimeRange, VizPanel } from '@grafana/scenes'; +import { + MultiValueVariable, + sceneGraph, + SceneGridLayout, + SceneGridRow, + SceneTimeRange, + VizPanel, +} from '@grafana/scenes'; import { Dashboard, LoadingState, Panel, RowPanel, VariableRefresh } from '@grafana/schema'; import { PanelModel } from 'app/features/dashboard/state'; import { getTimeRange } from 'app/features/dashboard/utils/timeRange'; @@ -1094,6 +1101,37 @@ describe('transformSceneToSaveModel', () => { expect((saveModel.panels![1] as any).options.content).toBe('new content'); }); }); + + describe('Given a scene with repeated panels and non-repeated panels', () => { + it('should save repeated panels itemHeight as height', () => { + const scene = transformSaveModelToScene({ dashboard: repeatingRowsAndPanelsDashboardJson as any, meta: {} }); + const gridItem = sceneGraph.findByKey(scene, 'grid-item-2') as DashboardGridItem; + expect(gridItem).toBeInstanceOf(DashboardGridItem); + expect(gridItem.state.height).toBe(10); + expect(gridItem.state.itemHeight).toBe(10); + expect(gridItem.state.itemHeight).toBe(10); + expect(gridItem.state.variableName).toBe('pod'); + gridItem.setState({ itemHeight: 24 }); + const saveModel = transformSceneToSaveModel(scene); + expect(saveModel.panels?.[3].gridPos?.h).toBe(24); + }); + + it('should not save non-repeated panels itemHeight as height', () => { + const scene = transformSaveModelToScene({ dashboard: repeatingRowsAndPanelsDashboardJson as any, meta: {} }); + const gridItem = sceneGraph.findByKey(scene, 'grid-item-15') as DashboardGridItem; + expect(gridItem).toBeInstanceOf(DashboardGridItem); + expect(gridItem.state.height).toBe(2); + expect(gridItem.state.itemHeight).toBe(2); + expect(gridItem.state.variableName).toBeUndefined(); + gridItem.setState({ itemHeight: 24 }); + let saveModel = transformSceneToSaveModel(scene); + expect(saveModel.panels?.[1].gridPos?.h).toBe(2); + + gridItem.setState({ height: 34 }); + saveModel = transformSceneToSaveModel(scene); + expect(saveModel.panels?.[1].gridPos?.h).toBe(34); + }); + }); }); export function buildGridItemFromPanelSchema(panel: Partial) { diff --git a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.ts b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.ts index b6aef4deccdbd..aed617f3a5cd9 100644 --- a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.ts +++ b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.ts @@ -199,7 +199,7 @@ export function gridItemToPanel( x = gridItem_.state.x ?? 0; y = gridItem_.state.y ?? 0; w = gridItem_.state.width ?? 0; - h = gridItem_.state.itemHeight ?? gridItem_.state.height ?? 0; + h = (gridItem_.state.variableName ? gridItem_.state.itemHeight : gridItem_.state.height) ?? 0; if (!vizPanel) { throw new Error('Unsupported grid item type'); diff --git a/public/app/features/dashboard-scene/settings/VersionsEditView.test.tsx b/public/app/features/dashboard-scene/settings/VersionsEditView.test.tsx index f9024d2b8edda..9e69917dfeeed 100644 --- a/public/app/features/dashboard-scene/settings/VersionsEditView.test.tsx +++ b/public/app/features/dashboard-scene/settings/VersionsEditView.test.tsx @@ -40,11 +40,11 @@ describe('VersionsEditView', () => { expect(versions).toHaveLength(3); expect(versions[0].createdDateString).toBe('2017-02-22 20:43:01'); - expect(versions[0].ageString).toBe('7 years ago'); + expect(versions[0].ageString).toBeDefined(); expect(versions[1].createdDateString).toBe('2017-02-22 20:43:01'); - expect(versions[1].ageString).toBe('7 years ago'); + expect(versions[1].ageString).toBeDefined(); expect(versions[2].createdDateString).toBe('2017-02-23 20:43:01'); - expect(versions[2].ageString).toBe('7 years ago'); + expect(versions[2].ageString).toBeDefined(); }); it('should bump the start threshold when fetching more versions', async () => { diff --git a/public/app/features/dashboard/state/DashboardModel.ts b/public/app/features/dashboard/state/DashboardModel.ts index fce70c7f03d1f..057d621d70620 100644 --- a/public/app/features/dashboard/state/DashboardModel.ts +++ b/public/app/features/dashboard/state/DashboardModel.ts @@ -19,7 +19,7 @@ import { } from '@grafana/data'; import { PromQuery } from '@grafana/prometheus'; import { RefreshEvent, TimeRangeUpdatedEvent, config } from '@grafana/runtime'; -import { Dashboard, DashboardLink } from '@grafana/schema'; +import { Dashboard, DashboardLink, VariableModel } from '@grafana/schema'; import { DEFAULT_ANNOTATION_COLOR } from '@grafana/ui'; import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT, REPEAT_DIR_VERTICAL } from 'app/core/constants'; import { contextSrv } from 'app/core/services/context_srv'; @@ -145,7 +145,7 @@ export class DashboardModel implements TimeModel { this.time = data.time ?? { from: 'now-6h', to: 'now' }; this.timepicker = data.timepicker ?? {}; this.liveNow = data.liveNow; - this.templating = this.ensureListExist(data.templating); + this.templating = this.removeNullValuesFromVariables(this.ensureListExist(data.templating)); this.annotations = this.ensureListExist(data.annotations); this.refresh = data.refresh; this.snapshot = data.snapshot; @@ -471,6 +471,28 @@ export class DashboardModel implements TimeModel { } } + private removeNullValuesFromVariables(templating: { list: VariableModel[] }) { + if (!templating.list.length) { + return templating; + } + + for (const variable of templating.list) { + if (variable.current) { + // this is a safeguard for null value that breaks scenes dashboards. + // expecting error at .includes(null) in order to not adjust + // VariableOption type to avoid breaking changes + if ( + variable.current.value === null || + //@ts-expect-error + (Array.isArray(variable.current.value) && variable.current.value.includes(null)) + ) { + variable.current = undefined; + } + } + } + return templating; + } + private ensureListExist(data: any = {}) { data.list ??= []; return data; diff --git a/public/app/plugins/datasource/azuremonitor/components/QueryEditor/QueryEditor.tsx b/public/app/plugins/datasource/azuremonitor/components/QueryEditor/QueryEditor.tsx index 6dfed0a21462e..a68223f2ebc10 100644 --- a/public/app/plugins/datasource/azuremonitor/components/QueryEditor/QueryEditor.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/QueryEditor/QueryEditor.tsx @@ -64,7 +64,9 @@ const QueryEditor = ({ options: datasource.getVariables().map((v) => ({ label: v, value: v })), }; - const isAzureAuthenticated = config.bootData.user.authenticatedBy === 'oauth_azuread'; + // Allow authproxy as it may not be clear if an authproxy user is authenticated by Azure + const isAzureAuthenticated = + config.bootData.user.authenticatedBy === 'oauth_azuread' || config.bootData.user.authenticatedBy === 'authproxy'; if (datasource.currentUserAuth) { if ( app === CoreApp.UnifiedAlerting && diff --git a/public/app/plugins/datasource/azuremonitor/package.json b/public/app/plugins/datasource/azuremonitor/package.json index bddf3c3bdbc38..1c09cb36d0954 100644 --- a/public/app/plugins/datasource/azuremonitor/package.json +++ b/public/app/plugins/datasource/azuremonitor/package.json @@ -2,14 +2,14 @@ "name": "@grafana-plugins/grafana-azure-monitor-datasource", "description": "Grafana data source for Azure Monitor", "private": true, - "version": "11.1.4", + "version": "11.1.5", "dependencies": { "@emotion/css": "11.11.2", - "@grafana/data": "11.1.4", + "@grafana/data": "11.1.5", "@grafana/experimental": "1.7.11", - "@grafana/runtime": "11.1.4", - "@grafana/schema": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/runtime": "11.1.5", + "@grafana/schema": "11.1.5", + "@grafana/ui": "11.1.5", "@kusto/monaco-kusto": "^10.0.0", "fast-deep-equal": "^3.1.3", "i18next": "^23.0.0", @@ -25,8 +25,8 @@ "tslib": "2.6.3" }, "devDependencies": { - "@grafana/e2e-selectors": "11.1.4", - "@grafana/plugin-configs": "11.1.4", + "@grafana/e2e-selectors": "11.1.5", + "@grafana/plugin-configs": "11.1.5", "@testing-library/dom": "10.0.0", "@testing-library/react": "15.0.2", "@testing-library/user-event": "14.5.2", diff --git a/public/app/plugins/datasource/cloud-monitoring/package.json b/public/app/plugins/datasource/cloud-monitoring/package.json index 63d280b9db1ac..b91d1f07481b9 100644 --- a/public/app/plugins/datasource/cloud-monitoring/package.json +++ b/public/app/plugins/datasource/cloud-monitoring/package.json @@ -2,15 +2,15 @@ "name": "@grafana-plugins/stackdriver", "description": "Grafana data source for Google Cloud Monitoring", "private": true, - "version": "11.1.4", + "version": "11.1.5", "dependencies": { "@emotion/css": "11.11.2", - "@grafana/data": "11.1.4", + "@grafana/data": "11.1.5", "@grafana/experimental": "1.7.11", "@grafana/google-sdk": "0.1.2", - "@grafana/runtime": "11.1.4", - "@grafana/schema": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/runtime": "11.1.5", + "@grafana/schema": "11.1.5", + "@grafana/ui": "11.1.5", "debounce-promise": "3.1.2", "fast-deep-equal": "^3.1.3", "i18next": "^23.0.0", @@ -26,8 +26,8 @@ "tslib": "2.6.3" }, "devDependencies": { - "@grafana/e2e-selectors": "11.1.4", - "@grafana/plugin-configs": "11.1.4", + "@grafana/e2e-selectors": "11.1.5", + "@grafana/plugin-configs": "11.1.5", "@testing-library/dom": "10.0.0", "@testing-library/react": "15.0.2", "@testing-library/user-event": "14.5.2", diff --git a/public/app/plugins/datasource/grafana-postgresql-datasource/package.json b/public/app/plugins/datasource/grafana-postgresql-datasource/package.json index aa57da768362b..32068c606f74f 100644 --- a/public/app/plugins/datasource/grafana-postgresql-datasource/package.json +++ b/public/app/plugins/datasource/grafana-postgresql-datasource/package.json @@ -2,22 +2,22 @@ "name": "@grafana-plugins/grafana-postgresql-datasource", "description": "PostgreSQL data source plugin", "private": true, - "version": "11.1.4", + "version": "11.1.5", "dependencies": { "@emotion/css": "11.11.2", - "@grafana/data": "11.1.4", + "@grafana/data": "11.1.5", "@grafana/experimental": "1.7.11", - "@grafana/runtime": "11.1.4", - "@grafana/sql": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/runtime": "11.1.5", + "@grafana/sql": "11.1.5", + "@grafana/ui": "11.1.5", "lodash": "4.17.21", "react": "18.2.0", "rxjs": "7.8.1", "tslib": "2.6.3" }, "devDependencies": { - "@grafana/e2e-selectors": "11.1.4", - "@grafana/plugin-configs": "11.1.4", + "@grafana/e2e-selectors": "11.1.5", + "@grafana/plugin-configs": "11.1.5", "@testing-library/react": "15.0.2", "@testing-library/user-event": "14.5.2", "@types/jest": "29.5.12", diff --git a/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json index 19510cbd77e08..e6e2b593cb2cd 100644 --- a/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json +++ b/public/app/plugins/datasource/grafana-pyroscope-datasource/package.json @@ -2,13 +2,13 @@ "name": "@grafana-plugins/grafana-pyroscope-datasource", "description": "Continuous profiling for analysis of CPU and memory usage, down to the line number and throughout time. Saving infrastructure cost, improving performance, and increasing reliability.", "private": true, - "version": "11.1.4", + "version": "11.1.5", "dependencies": { "@emotion/css": "11.11.2", - "@grafana/data": "11.1.4", - "@grafana/runtime": "11.1.4", - "@grafana/schema": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/data": "11.1.5", + "@grafana/runtime": "11.1.5", + "@grafana/schema": "11.1.5", + "@grafana/ui": "11.1.5", "fast-deep-equal": "^3.1.3", "lodash": "4.17.21", "monaco-editor": "0.34.1", @@ -20,7 +20,7 @@ "tslib": "2.6.3" }, "devDependencies": { - "@grafana/plugin-configs": "11.1.4", + "@grafana/plugin-configs": "11.1.5", "@testing-library/dom": "10.0.0", "@testing-library/jest-dom": "6.4.2", "@testing-library/react": "15.0.2", diff --git a/public/app/plugins/datasource/grafana-testdata-datasource/package.json b/public/app/plugins/datasource/grafana-testdata-datasource/package.json index 0fd4e9213a708..387eb6cffeb90 100644 --- a/public/app/plugins/datasource/grafana-testdata-datasource/package.json +++ b/public/app/plugins/datasource/grafana-testdata-datasource/package.json @@ -2,14 +2,14 @@ "name": "@grafana-plugins/grafana-testdata-datasource", "description": "Generates test data in different forms", "private": true, - "version": "11.1.4", + "version": "11.1.5", "dependencies": { "@emotion/css": "11.11.2", - "@grafana/data": "11.1.4", + "@grafana/data": "11.1.5", "@grafana/experimental": "1.7.11", - "@grafana/runtime": "11.1.4", - "@grafana/schema": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/runtime": "11.1.5", + "@grafana/schema": "11.1.5", + "@grafana/ui": "11.1.5", "d3-random": "^3.0.1", "lodash": "4.17.21", "micro-memoize": "^4.1.2", @@ -22,8 +22,8 @@ "uuid": "9.0.1" }, "devDependencies": { - "@grafana/e2e-selectors": "11.1.4", - "@grafana/plugin-configs": "11.1.4", + "@grafana/e2e-selectors": "11.1.5", + "@grafana/plugin-configs": "11.1.5", "@testing-library/dom": "10.0.0", "@testing-library/react": "15.0.2", "@testing-library/user-event": "14.5.2", diff --git a/public/app/plugins/datasource/jaeger/package.json b/public/app/plugins/datasource/jaeger/package.json index 4f797e148624c..d66f3bb0044f2 100644 --- a/public/app/plugins/datasource/jaeger/package.json +++ b/public/app/plugins/datasource/jaeger/package.json @@ -2,7 +2,7 @@ "name": "@grafana-plugins/jaeger", "description": "Jaeger plugin for Grafana", "private": true, - "version": "11.1.4", + "version": "11.1.5", "dependencies": { "@emotion/css": "11.11.2", "@grafana/data": "workspace:*", diff --git a/public/app/plugins/datasource/loki/datasource.test.ts b/public/app/plugins/datasource/loki/datasource.test.ts index 37cb65cf67619..552194775bada 100644 --- a/public/app/plugins/datasource/loki/datasource.test.ts +++ b/public/app/plugins/datasource/loki/datasource.test.ts @@ -280,16 +280,18 @@ describe('LokiDatasource', () => { }; const query: LokiQuery = { expr: originalQuery, refId: 'A' }; const ds = createLokiDatasource(templateSrv); - const adhocFilters = [ + const adhocFilters: AdHocFilter[] = [ { key: 'k1', operator: '=', value: 'v1', + condition: '', }, { key: 'k2', operator: '!=', value: 'v2', + condition: '', }, ]; jest.spyOn(ds, 'addAdHocFilters'); @@ -302,6 +304,13 @@ describe('LokiDatasource', () => { expect(ds.applyTemplateVariables(query, {}, adhocFilters).expr).toBe( 'rate({bar="baz", job="foo", k1="v1", k2!="v2"} |= "bar" [5m])' ); + + assertAdHocFilters( + originalQuery, + 'rate({bar="baz", job="foo", k1="v1", k2!="v2"} |= "bar" [$__auto])', + ds, + adhocFilters + ); }); }); @@ -1284,6 +1293,36 @@ describe('LokiDatasource', () => { assertAdHocFilters('{job="grafana"}', '{job="grafana", instance=~".*"}', ds, defaultAdHocFilters); }); }); + + describe('bug', () => { + beforeEach(() => { + ds = createLokiDatasource(); + }); + const defaultAdHocFilters: AdHocFilter[] = [ + { + key: 'service_name', + operator: '=', + value: 'grafana/hosted-grafana-gateway', + condition: '', + }, + ]; + it('should not add indexed fields twice as index filter and line filter, backtick', () => { + assertAdHocFilters( + '{service_name=`grafana/hosted-grafana-gateway`} | logfmt', + '{service_name="grafana/hosted-grafana-gateway"} | logfmt', + ds, + defaultAdHocFilters + ); + }); + it('should not add indexed fields twice as index filter and line filter, quotes', () => { + assertAdHocFilters( + '{service_name="grafana/hosted-grafana-gateway"} | logfmt', + '{service_name="grafana/hosted-grafana-gateway"} | logfmt', + ds, + defaultAdHocFilters + ); + }); + }); }); describe('logs volume data provider', () => { diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index a8763c0a7645b..c9cd293cdf37c 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -1032,7 +1032,7 @@ export class LokiDatasource * @todo this.templateSrv.getAdhocFilters() is deprecated */ addAdHocFilters(queryExpr: string, adhocFilters?: AdHocVariableFilter[]) { - if (!adhocFilters) { + if (!adhocFilters?.length) { return queryExpr; } diff --git a/public/app/plugins/datasource/loki/modifyQuery.test.ts b/public/app/plugins/datasource/loki/modifyQuery.test.ts index 2a1598dcc2012..5ad9b36022f59 100644 --- a/public/app/plugins/datasource/loki/modifyQuery.test.ts +++ b/public/app/plugins/datasource/loki/modifyQuery.test.ts @@ -6,6 +6,8 @@ import { addLineFilter, addNoPipelineErrorToQuery, addParserToQuery, + getIdentifierInStreamPositions, + getStreamSelectorPositions, NodePosition, queryHasFilter, removeCommentsFromQuery, @@ -15,55 +17,64 @@ import { LabelType } from './types'; describe('addLabelToQuery()', () => { it.each` - query | description | label | operator | value | expectedResult - ${'{x="y"}'} | ${'no label and value'} | ${''} | ${'='} | ${''} | ${''} - ${'{x="yy"}'} | ${'simple query'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="yy", bar="baz"}'} - ${'{x="yy"}'} | ${'simple query'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="yy", bar="baz"}'} - ${'{x="yy"}'} | ${'custom operator'} | ${'bar'} | ${'!='} | ${'baz'} | ${'{x="yy", bar!="baz"}'} - ${'rate({}[1m])'} | ${'do not modify ranges'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({bar="baz"}[1m])'} - ${'sum by (host) (rate({} [1m]))'} | ${'detect in-order function use'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum by (host) (rate({bar="baz"}[1m]))'} - ${'{instance="my-host.com:9100"}'} | ${'selectors with punctuation'} | ${'bar'} | ${'='} | ${'baz'} | ${'{instance="my-host.com:9100", bar="baz"}'} - ${'{list="a,b,c"}'} | ${'selectors with punctuation'} | ${'bar'} | ${'='} | ${'baz'} | ${'{list="a,b,c", bar="baz"}'} - ${'rate({}[5m]) + rate({}[5m])'} | ${'arithmetical expressions'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({bar="baz"}[5m]) + rate({bar="baz"}[5m])'} - ${'avg(rate({x="y"} [$__interval]))+ sum(rate({}[5m]))'} | ${'arithmetical expressions'} | ${'bar'} | ${'='} | ${'baz'} | ${'avg(rate({x="y", bar="baz"} [$__interval]))+ sum(rate({bar="baz"}[5m]))'} - ${'rate({x="yy"}[5m]) * rate({y="zz",a="bb"}[5m]) * rate({}[5m])'} | ${'arithmetical expressions'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({x="yy", bar="baz"}[5m]) * rate({y="zz", a="bb", bar="baz"}[5m]) * rate({bar="baz"}[5m])'} - ${'{x="yy", bar!="baz"}'} | ${'do not add duplicate labels'} | ${'bar'} | ${'!='} | ${'baz'} | ${'{x="yy", bar!="baz"}'} - ${'rate({bar="baz"}[1m])'} | ${'do not add duplicate labels'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({bar="baz"}[1m])'} - ${'{list="a,b,c", bar="baz"}'} | ${'do not add duplicate labels'} | ${'bar'} | ${'='} | ${'baz'} | ${'{list="a,b,c", bar="baz"}'} - ${'avg(rate({bar="baz"} [$__interval]))+ sum(rate({bar="baz"}[5m]))'} | ${'do not add duplicate labels'} | ${'bar'} | ${'='} | ${'baz'} | ${'avg(rate({bar="baz"} [$__interval]))+ sum(rate({bar="baz"}[5m]))'} - ${'{x="y"} |="yy"'} | ${'do not remove filters'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="y", bar="baz"} |="yy"'} - ${'{x="y"} |="yy" !~"xx"'} | ${'do not remove filters'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="y", bar="baz"} |="yy" !~"xx"'} - ${'{x="y"} or {}'} | ${'metric with logical operators'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="y", bar="baz"} or {bar="baz"}'} - ${'{x="y"} and {}'} | ${'metric with logical operators'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="y", bar="baz"} and {bar="baz"}'} - ${'sum(rate({job="foo"}[2m])) by (value $variable)'} | ${'template variables'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum(rate({job="foo", bar="baz"}[2m])) by (value $variable)'} - ${'rate({x="y"}[${__range_s}s])'} | ${'metric query with range grafana variable'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({x="y", bar="baz"}[${__range_s}s])'} - ${'max by (id, name, type) ({type=~"foo|bar|baz-test"}) * on(id) group_right(id, type, name) sum by (id) (rate({} [5m])) * 1000'} | ${'metric query with labels in label list with the group modifier'} | ${'bar'} | ${'='} | ${'baz'} | ${'max by (id, name, type) ({type=~"foo|bar|baz-test", bar="baz"}) * on(id) group_right(id, type, name) sum by (id) (rate({bar="baz"}[5m])) * 1000'} - ${'{foo="bar"} | logfmt'} | ${'query with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | bar=`baz`'} - ${'{foo="bar"} | logfmt | json'} | ${'query with multiple parsers'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | json | bar=`baz`'} - ${'{foo="bar"} | logfmt | x="y"'} | ${'query with parser and label filter'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | x="y" | bar=`baz`'} - ${'rate({foo="bar"} | logfmt [5m])'} | ${'metric query with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({foo="bar"} | logfmt | bar=`baz` [5m])'} - ${'sum by(host) (rate({foo="bar"} | logfmt | x="y" | line_format "{{.status}}" [5m]))'} | ${'metric query with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum by(host) (rate({foo="bar"} | logfmt | x="y" | bar=`baz` | line_format "{{.status}}" [5m]))'} - ${'sum by(host) (rate({foo="bar"} | logfmt | x="y" | label_format process="{{.process}}" [5m]))'} | ${'metric query with parser and label format'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum by(host) (rate({foo="bar"} | logfmt | x="y" | label_format process="{{.process}}" | bar=`baz` [5m]))'} - ${'{foo="bar"} | logfmt | x="y" | label_format process="{{.process}}"'} | ${'query with parser and label format'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | x="y" | label_format process="{{.process}}" | bar=`baz`'} - ${'{foo="bar"} | logfmt | line_format "{{.status}}"'} | ${'do not add filter to line_format expressions in query with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | bar=`baz` | line_format "{{.status}}"'} - ${'{foo="bar"} | logfmt | line_format "{{status}}"'} | ${'do not add filter to line_format expressions in query with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | bar=`baz` | line_format "{{status}}"'} - ${'{}'} | ${'query without stream selector'} | ${'bar'} | ${'='} | ${'baz'} | ${'{bar="baz"}'} - ${'{} | logfmt'} | ${'query without stream selector and with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'{bar="baz"}| logfmt'} - ${'{} | x="y"'} | ${'query without stream selector and with label filter'} | ${'bar'} | ${'='} | ${'baz'} | ${'{bar="baz"}| x="y"'} - ${'{} | logfmt | x="y"'} | ${'query without stream selector and with parser and label filter'} | ${'bar'} | ${'='} | ${'baz'} | ${'{bar="baz"}| logfmt | x="y"'} - ${'sum(rate({x="y"} [5m])) + sum(rate({} | logfmt [5m]))'} | ${'metric query with 1 empty and 1 not empty stream selector with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum(rate({x="y", bar="baz"} [5m])) + sum(rate({bar="baz"}| logfmt [5m]))'} - ${'sum(rate({x="y"} | logfmt [5m])) + sum(rate({} [5m]))'} | ${'metric query with 1 non-empty and 1 not empty stream selector with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum(rate({x="y", bar="baz"} | logfmt [5m])) + sum(rate({bar="baz"}[5m]))'} - ${'{x="yy"}'} | ${'simple query with escaped value'} | ${'bar'} | ${'='} | ${'"baz"'} | ${'{x="yy", bar=""baz""}'} - ${'{x="yy"}'} | ${'simple query with escaped value'} | ${'bar'} | ${'='} | ${'\\"baz\\"'} | ${'{x="yy", bar="\\"baz\\""}'} - ${'{x="yy"}'} | ${'simple query with an other escaped value'} | ${'bar'} | ${'='} | ${'baz\\\\'} | ${'{x="yy", bar="baz\\\\"}'} - ${'{x="yy"}'} | ${'simple query with escaped value and regex operator'} | ${'bar'} | ${'~='} | ${'baz\\\\'} | ${'{x="yy", bar~="baz\\\\"}'} - ${'{foo="bar"} | logfmt'} | ${'query with parser with escaped value'} | ${'bar'} | ${'='} | ${'\\"baz\\"'} | ${'{foo="bar"} | logfmt | bar=`"baz"`'} - ${'{foo="bar"} | logfmt'} | ${'query with parser with an other escaped value'} | ${'bar'} | ${'='} | ${'baz\\\\'} | ${'{foo="bar"} | logfmt | bar=`baz\\`'} - ${'{foo="bar"} | logfmt'} | ${'query with parser with escaped value and regex operator'} | ${'bar'} | ${'~='} | ${'\\"baz\\"'} | ${'{foo="bar"} | logfmt | bar~=`"baz"`'} - ${'{foo="bar"} | logfmt'} | ${'query with parser with escaped value and regex operator'} | ${'bar'} | ${'~='} | ${'\\"baz\\"'} | ${'{foo="bar"} | logfmt | bar~=`"baz"`'} - ${'{foo="bar"} | logfmt'} | ${'query with parser, > operator and number value'} | ${'bar'} | ${'>'} | ${'5'} | ${'{foo="bar"} | logfmt | bar>5'} - ${'{foo="bar"} | logfmt'} | ${'query with parser, < operator and non-number value'} | ${'bar'} | ${'<'} | ${'5KiB'} | ${'{foo="bar"} | logfmt | bar<`5KiB`'} - ${'sum(rate({x="y"} | logfmt [5m])) + sum(rate({x="z"} | logfmt [5m]))'} | ${'metric query with non empty selectors and parsers'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum(rate({x="y"} | logfmt | bar=`baz` [5m])) + sum(rate({x="z"} | logfmt | bar=`baz` [5m]))'} + query | description | label | operator | value | expectedResult + ${'{x="y"}'} | ${'no label and value'} | ${''} | ${'='} | ${''} | ${''} + ${'{x="yy"}'} | ${'simple query'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="yy", bar="baz"}'} + ${'{x="yy"}'} | ${'simple query'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="yy", bar="baz"}'} + ${'{x="yy"}'} | ${'custom operator'} | ${'bar'} | ${'!='} | ${'baz'} | ${'{x="yy", bar!="baz"}'} + ${'rate({}[1m])'} | ${'do not modify ranges'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({bar="baz"}[1m])'} + ${'sum by (host) (rate({} [1m]))'} | ${'detect in-order function use'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum by (host) (rate({bar="baz"}[1m]))'} + ${'{instance="my-host.com:9100"}'} | ${'selectors with punctuation'} | ${'bar'} | ${'='} | ${'baz'} | ${'{instance="my-host.com:9100", bar="baz"}'} + ${'{list="a,b,c"}'} | ${'selectors with punctuation'} | ${'bar'} | ${'='} | ${'baz'} | ${'{list="a,b,c", bar="baz"}'} + ${'rate({}[5m]) + rate({}[5m])'} | ${'arithmetical expressions'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({bar="baz"}[5m]) + rate({bar="baz"}[5m])'} + ${'avg(rate({x="y"} [$__interval]))+ sum(rate({}[5m]))'} | ${'arithmetical expressions'} | ${'bar'} | ${'='} | ${'baz'} | ${'avg(rate({x="y", bar="baz"} [$__interval]))+ sum(rate({bar="baz"}[5m]))'} + ${'rate({x="yy"}[5m]) * rate({y="zz",a="bb"}[5m]) * rate({}[5m])'} | ${'arithmetical expressions'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({x="yy", bar="baz"}[5m]) * rate({y="zz", a="bb", bar="baz"}[5m]) * rate({bar="baz"}[5m])'} + ${'{x="yy", bar!="baz"}'} | ${'do not add duplicate labels'} | ${'bar'} | ${'!='} | ${'baz'} | ${'{x="yy", bar!="baz"}'} + ${'rate({bar="baz"}[1m])'} | ${'do not add duplicate labels'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({bar="baz"}[1m])'} + ${'{list="a,b,c", bar="baz"}'} | ${'do not add duplicate labels'} | ${'bar'} | ${'='} | ${'baz'} | ${'{list="a,b,c", bar="baz"}'} + ${'avg(rate({bar="baz"} [$__interval]))+ sum(rate({bar="baz"}[5m]))'} | ${'do not add duplicate labels'} | ${'bar'} | ${'='} | ${'baz'} | ${'avg(rate({bar="baz"} [$__interval]))+ sum(rate({bar="baz"}[5m]))'} + ${'{x="y"} |="yy"'} | ${'do not remove filters'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="y", bar="baz"} |="yy"'} + ${'{x="y"} |="yy" !~"xx"'} | ${'do not remove filters'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="y", bar="baz"} |="yy" !~"xx"'} + ${'{x="y"} or {}'} | ${'metric with logical operators'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="y", bar="baz"} or {bar="baz"}'} + ${'{x="y"} and {}'} | ${'metric with logical operators'} | ${'bar'} | ${'='} | ${'baz'} | ${'{x="y", bar="baz"} and {bar="baz"}'} + ${'sum(rate({job="foo"}[2m])) by (value $variable)'} | ${'template variables'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum(rate({job="foo", bar="baz"}[2m])) by (value $variable)'} + ${'rate({x="y"}[${__range_s}s])'} | ${'metric query with range grafana variable'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({x="y", bar="baz"}[${__range_s}s])'} + ${'max by (id, name, type) ({type=~"foo|bar|baz-test"}) * on(id) group_right(id, type, name) sum by (id) (rate({} [5m])) * 1000'} | ${'metric query with labels in label list with the group modifier'} | ${'bar'} | ${'='} | ${'baz'} | ${'max by (id, name, type) ({type=~"foo|bar|baz-test", bar="baz"}) * on(id) group_right(id, type, name) sum by (id) (rate({bar="baz"}[5m])) * 1000'} + ${'{foo="bar"} | logfmt'} | ${'query with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | bar=`baz`'} + ${'{foo="bar"} | logfmt | json'} | ${'query with multiple parsers'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | json | bar=`baz`'} + ${'{foo="bar"} | logfmt | x="y"'} | ${'query with parser and label filter'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | x="y" | bar=`baz`'} + ${'rate({foo="bar"} | logfmt [5m])'} | ${'metric query with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'rate({foo="bar"} | logfmt | bar=`baz` [5m])'} + ${'sum by(host) (rate({foo="bar"} | logfmt | x="y" | line_format "{{.status}}" [5m]))'} | ${'metric query with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum by(host) (rate({foo="bar"} | logfmt | x="y" | bar=`baz` | line_format "{{.status}}" [5m]))'} + ${'sum by(host) (rate({foo="bar"} | logfmt | x="y" | label_format process="{{.process}}" [5m]))'} | ${'metric query with parser and label format'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum by(host) (rate({foo="bar"} | logfmt | x="y" | label_format process="{{.process}}" | bar=`baz` [5m]))'} + ${'{foo="bar"} | logfmt | x="y" | label_format process="{{.process}}"'} | ${'query with parser and label format'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | x="y" | label_format process="{{.process}}" | bar=`baz`'} + ${'{foo="bar"} | logfmt | line_format "{{.status}}"'} | ${'do not add filter to line_format expressions in query with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | bar=`baz` | line_format "{{.status}}"'} + ${'{foo="bar"} | logfmt | line_format "{{status}}"'} | ${'do not add filter to line_format expressions in query with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'{foo="bar"} | logfmt | bar=`baz` | line_format "{{status}}"'} + ${'{}'} | ${'query without stream selector'} | ${'bar'} | ${'='} | ${'baz'} | ${'{bar="baz"}'} + ${'{} | logfmt'} | ${'query without stream selector and with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'{bar="baz"}| logfmt'} + ${'{} | x="y"'} | ${'query without stream selector and with label filter'} | ${'bar'} | ${'='} | ${'baz'} | ${'{bar="baz"}| x="y"'} + ${'{} | logfmt | x="y"'} | ${'query without stream selector and with parser and label filter'} | ${'bar'} | ${'='} | ${'baz'} | ${'{bar="baz"}| logfmt | x="y"'} + ${'sum(rate({x="y"} [5m])) + sum(rate({} | logfmt [5m]))'} | ${'metric query with 1 empty and 1 not empty stream selector with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum(rate({x="y", bar="baz"} [5m])) + sum(rate({bar="baz"}| logfmt [5m]))'} + ${'sum(rate({x="y"} | logfmt [5m])) + sum(rate({} [5m]))'} | ${'metric query with 1 non-empty and 1 not empty stream selector with parser'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum(rate({x="y", bar="baz"} | logfmt [5m])) + sum(rate({bar="baz"}[5m]))'} + ${'sum(rate({x="y", bar="baz"} | logfmt [5m])) + sum(rate({x="y", bar="baz"} [5m]))'} | ${'metric query with two duplicate stream selectors'} | ${'x'} | ${'='} | ${'y'} | ${'sum(rate({x="y", bar="baz"} | logfmt [5m])) + sum(rate({x="y", bar="baz"} [5m]))'} + ${'{x="yy"}'} | ${'simple query with escaped value'} | ${'bar'} | ${'='} | ${'"baz"'} | ${'{x="yy", bar=""baz""}'} + ${'{x="yy"}'} | ${'simple query with escaped value'} | ${'bar'} | ${'='} | ${'\\"baz\\"'} | ${'{x="yy", bar="\\"baz\\""}'} + ${'{x="yy"}'} | ${'simple query with an other escaped value'} | ${'bar'} | ${'='} | ${'baz\\\\'} | ${'{x="yy", bar="baz\\\\"}'} + ${'{x="yy"}'} | ${'simple query with escaped value and regex operator'} | ${'bar'} | ${'~='} | ${'baz\\\\'} | ${'{x="yy", bar~="baz\\\\"}'} + ${'{foo="bar"} | logfmt'} | ${'query with parser with escaped value'} | ${'bar'} | ${'='} | ${'\\"baz\\"'} | ${'{foo="bar"} | logfmt | bar=`"baz"`'} + ${'{foo=`"bar"`} | logfmt'} | ${'query with label already added to stream selector, doublequotes/backticks'} | ${'foo'} | ${'='} | ${`"bar"`} | ${'{foo=""bar""} | logfmt'} + ${'{foo="\\"bar\\""`} | logfmt'} | ${'query with label already added to stream selector, doublequotes/escaped'} | ${'foo'} | ${'='} | ${'\\"bar\\"'} | ${'{foo="\\"bar\\""} | logfmt'} + ${'{foo="bar"} | logfmt'} | ${'query with label already added to stream selector, doublequotes unescaped'} | ${'foo'} | ${'='} | ${'bar'} | ${'{foo="bar"} | logfmt'} + ${'{foo=`bar`} | logfmt'} | ${'query with label already added to stream selector, backticks'} | ${'foo'} | ${'='} | ${'bar'} | ${'{foo="bar"} | logfmt'} + ${'{service_name=`grafana/hosted-grafana-gateway`} | logfmt | caller!=`handler.go:637` '} | ${'query with parser and line filter, backticks'} | ${'service_name'} | ${'='} | ${'grafana/hosted-grafana-gateway'} | ${'{service_name="grafana/hosted-grafana-gateway"} | logfmt | caller!=`handler.go:637` '} + ${'{service_name=`grafana/hosted-grafana-gateway`, pod_template_hash!=`5fd76866f4`} | logfmt | caller!=`handler.go:637`'} | ${'query with parser and line filter, multiple stream selectors'} | ${'service_name'} | ${'='} | ${'grafana/hosted-grafana-gateway'} | ${'{service_name="grafana/hosted-grafana-gateway", pod_template_hash!="5fd76866f4"} | logfmt | caller!=`handler.go:637`'} + ${'{service_name=`grafana/hosted-grafana-gateway`, x!=`y`} | logfmt | caller!=`handler.go:637`'} | ${'query with parser and line filter, multiple stream selectors, value2'} | ${'x'} | ${'!='} | ${'y'} | ${'{service_name="grafana/hosted-grafana-gateway", x!="y"} | logfmt | caller!=`handler.go:637`'} + ${'{service_name="grafana/hosted-grafana-gateway"} | logfmt | caller!=`handler.go:637` '} | ${'query with parser and line filter, doublequotes'} | ${'service_name'} | ${'='} | ${'grafana/hosted-grafana-gateway'} | ${'{service_name="grafana/hosted-grafana-gateway"} | logfmt | caller!=`handler.go:637` '} + ${'{foo="bar"} | logfmt'} | ${'query with parser with an other escaped value'} | ${'bar'} | ${'='} | ${'baz\\\\'} | ${'{foo="bar"} | logfmt | bar=`baz\\`'} + ${'{foo="bar"} | logfmt'} | ${'query with parser with escaped value and regex operator'} | ${'bar'} | ${'~='} | ${'\\"baz\\"'} | ${'{foo="bar"} | logfmt | bar~=`"baz"`'} + ${'{foo="bar"} | logfmt'} | ${'query with parser with escaped value and regex operator'} | ${'bar'} | ${'~='} | ${'\\"baz\\"'} | ${'{foo="bar"} | logfmt | bar~=`"baz"`'} + ${'{foo="bar"} | logfmt'} | ${'query with parser, > operator and number value'} | ${'bar'} | ${'>'} | ${'5'} | ${'{foo="bar"} | logfmt | bar>5'} + ${'{foo="bar"} | logfmt'} | ${'query with parser, < operator and non-number value'} | ${'bar'} | ${'<'} | ${'5KiB'} | ${'{foo="bar"} | logfmt | bar<`5KiB`'} + ${'sum(rate({x="y"} | logfmt [5m])) + sum(rate({x="z"} | logfmt [5m]))'} | ${'metric query with non empty selectors and parsers'} | ${'bar'} | ${'='} | ${'baz'} | ${'sum(rate({x="y"} | logfmt | bar=`baz` [5m])) + sum(rate({x="z"} | logfmt | bar=`baz` [5m]))'} `( 'should add label to query: $query, description: $description', ({ query, description, label, operator, value, expectedResult }) => { @@ -353,3 +364,88 @@ describe.each(['|=', '!='])('addLineFilter type %s', (op: string) => { ); }); }); + +describe('getStreamSelectorPositions', () => { + it('should parse position of stream selectors', () => { + expect( + getStreamSelectorPositions('sum(rate({x="y", bar="baz"} | logfmt [5m])) + sum(rate({x="y", bar="baz"} [5m]))') + ).toEqual([ + { + from: 9, + to: 27, + type: { + name: 'Selector', + props: {}, + id: 40, + flags: 0, + }, + }, + { + from: 55, + to: 73, + type: { + name: 'Selector', + props: {}, + id: 40, + flags: 0, + }, + }, + ]); + }); +}); +describe('getIdentifierInStreamPositions', () => { + it('should parse position of stream selectors', () => { + const indexedKeys = ['x', 'bar']; + const expr = `sum(rate({${indexedKeys[0]}="y", ${indexedKeys[1]}="baz"} | logfmt | x |= "x=y" |= "bar=baz" [5m])) + sum(rate({${indexedKeys[0]}="y", ${indexedKeys[1]}="baz"} [5m]))`; + const identifiers = getIdentifierInStreamPositions(expr); + identifiers.forEach((identifier, index) => { + expect(identifier.getExpression(expr)).toEqual(indexedKeys[index % 2]); + }); + expect(identifiers).toEqual([ + //x1 + { + from: 10, + to: 11, + type: { + name: 'Identifier', + props: {}, + id: 43, + flags: 0, + }, + }, + //bar1 + { + from: 17, + to: 20, + type: { + name: 'Identifier', + props: {}, + id: 43, + flags: 0, + }, + }, + //x2 + { + from: 82, + to: 83, + type: { + name: 'Identifier', + props: {}, + id: 43, + flags: 0, + }, + }, + //bar2 + { + from: 89, + to: 92, + type: { + name: 'Identifier', + props: {}, + id: 43, + flags: 0, + }, + }, + ]); + }); +}); diff --git a/public/app/plugins/datasource/loki/modifyQuery.ts b/public/app/plugins/datasource/loki/modifyQuery.ts index 2f8e2c8c72b10..293d78fc66089 100644 --- a/public/app/plugins/datasource/loki/modifyQuery.ts +++ b/public/app/plugins/datasource/loki/modifyQuery.ts @@ -165,6 +165,16 @@ export function addLabelToQuery( const hasStreamSelectorMatchers = getMatcherInStreamPositions(query); // For non-indexed labels we want to add them after label_format to, for example, allow ad-hoc filters to use formatted labels const labelFormatPositions = getNodePositionsFromQuery(query, [LabelFormatExpr]); + + // If the label type wasn't passed in from the calling function, we can use lezer to figure out if this label is already in the stream selectors + if (!labelType) { + const identifierSelectorMatchers = getIdentifierInStreamPositions(query); + const indexedKeys = identifierSelectorMatchers.map((match) => match.getExpression(query)); + if (indexedKeys.includes(key)) { + labelType = LabelType.Indexed; + } + } + const everyStreamSelectorHasMatcher = streamSelectorPositions.every((streamSelectorPosition) => hasStreamSelectorMatchers.some( (matcherPosition) => @@ -621,3 +631,16 @@ function getMatcherInStreamPositions(query: string): NodePosition[] { }); return positions; } + +export function getIdentifierInStreamPositions(query: string): NodePosition[] { + const tree = parser.parse(query); + const positions: NodePosition[] = []; + tree.iterate({ + enter: ({ node }): false | void => { + if (node.type.id === Selector) { + positions.push(...getAllPositionsInNodeByType(node, Identifier)); + } + }, + }); + return positions; +} diff --git a/public/app/plugins/datasource/mysql/package.json b/public/app/plugins/datasource/mysql/package.json index d5c6bd0e66205..8d8dcfa9d7c1e 100644 --- a/public/app/plugins/datasource/mysql/package.json +++ b/public/app/plugins/datasource/mysql/package.json @@ -2,22 +2,22 @@ "name": "@grafana-plugins/mysql", "description": "MySQL data source plugin", "private": true, - "version": "11.1.4", + "version": "11.1.5", "dependencies": { "@emotion/css": "11.11.2", - "@grafana/data": "11.1.4", + "@grafana/data": "11.1.5", "@grafana/experimental": "1.7.11", - "@grafana/runtime": "11.1.4", - "@grafana/sql": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/runtime": "11.1.5", + "@grafana/sql": "11.1.5", + "@grafana/ui": "11.1.5", "lodash": "4.17.21", "react": "18.2.0", "rxjs": "7.8.1", "tslib": "2.6.3" }, "devDependencies": { - "@grafana/e2e-selectors": "11.1.4", - "@grafana/plugin-configs": "11.1.4", + "@grafana/e2e-selectors": "11.1.5", + "@grafana/plugin-configs": "11.1.5", "@testing-library/react": "15.0.2", "@testing-library/user-event": "14.5.2", "@types/jest": "29.5.12", diff --git a/public/app/plugins/datasource/parca/package.json b/public/app/plugins/datasource/parca/package.json index c7314eccff270..d3417d5c23821 100644 --- a/public/app/plugins/datasource/parca/package.json +++ b/public/app/plugins/datasource/parca/package.json @@ -2,13 +2,13 @@ "name": "@grafana-plugins/parca", "description": "Continuous profiling for analysis of CPU and memory usage, down to the line number and throughout time. Saving infrastructure cost, improving performance, and increasing reliability.", "private": true, - "version": "11.1.4", + "version": "11.1.5", "dependencies": { "@emotion/css": "11.11.2", - "@grafana/data": "11.1.4", - "@grafana/runtime": "11.1.4", - "@grafana/schema": "11.1.4", - "@grafana/ui": "11.1.4", + "@grafana/data": "11.1.5", + "@grafana/runtime": "11.1.5", + "@grafana/schema": "11.1.5", + "@grafana/ui": "11.1.5", "lodash": "4.17.21", "monaco-editor": "0.34.1", "react": "18.2.0", @@ -18,7 +18,7 @@ "tslib": "2.6.3" }, "devDependencies": { - "@grafana/plugin-configs": "11.1.4", + "@grafana/plugin-configs": "11.1.5", "@testing-library/dom": "10.0.0", "@testing-library/react": "15.0.2", "@testing-library/user-event": "14.5.2", diff --git a/public/app/plugins/datasource/prometheus/plugin.json b/public/app/plugins/datasource/prometheus/plugin.json index 356b924dbb021..c11bd2e98090e 100644 --- a/public/app/plugins/datasource/prometheus/plugin.json +++ b/public/app/plugins/datasource/prometheus/plugin.json @@ -38,31 +38,31 @@ "method": "GET", "path": "/rules", "reqRole": "Viewer", - "reqAction": "datasources:query" + "reqAction": "alert.rules.external:read" }, { "method": "POST", "path": "/rules", "reqRole": "Editor", - "reqAction": "datasources:write" + "reqAction": "alert.rules.external:write" }, { "method": "DELETE", "path": "/rules", "reqRole": "Editor", - "reqAction": "datasources:write" + "reqAction": "alert.rules.external:write" }, { "method": "DELETE", "path": "/config/v1/rules", "reqRole": "Editor", - "reqAction": "datasources:write" + "reqAction": "alert.rules.external:write" }, { "method": "POST", "path": "/config/v1/rules", "reqRole": "Editor", - "reqAction": "datasources:write" + "reqAction": "alert.rules.external:write" } ], "includes": [ diff --git a/public/app/plugins/datasource/tempo/package.json b/public/app/plugins/datasource/tempo/package.json index 005e0e7b04428..661a0b7182de2 100644 --- a/public/app/plugins/datasource/tempo/package.json +++ b/public/app/plugins/datasource/tempo/package.json @@ -2,7 +2,7 @@ "name": "@grafana-plugins/tempo", "description": "Grafana plugin for the Tempo data source.", "private": true, - "version": "11.1.4", + "version": "11.1.5", "dependencies": { "@emotion/css": "11.11.2", "@grafana/data": "workspace:*", @@ -39,7 +39,7 @@ "uuid": "9.0.1" }, "devDependencies": { - "@grafana/plugin-configs": "11.1.4", + "@grafana/plugin-configs": "11.1.5", "@testing-library/dom": "10.0.0", "@testing-library/jest-dom": "6.4.2", "@testing-library/react": "15.0.2", diff --git a/public/app/plugins/datasource/zipkin/package.json b/public/app/plugins/datasource/zipkin/package.json index e128d109f8c38..7f126522a61a3 100644 --- a/public/app/plugins/datasource/zipkin/package.json +++ b/public/app/plugins/datasource/zipkin/package.json @@ -2,7 +2,7 @@ "name": "@grafana-plugins/zipkin", "description": "Zipkin plugin for Grafana", "private": true, - "version": "11.1.4", + "version": "11.1.5", "dependencies": { "@emotion/css": "11.11.2", "@grafana/data": "workspace:*", diff --git a/yarn.lock b/yarn.lock index 2a3b62554c585..3959e9d406d9b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2645,13 +2645,13 @@ __metadata: resolution: "@grafana-plugins/grafana-azure-monitor-datasource@workspace:public/app/plugins/datasource/azuremonitor" dependencies: "@emotion/css": "npm:11.11.2" - "@grafana/data": "npm:11.1.4" - "@grafana/e2e-selectors": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/e2e-selectors": "npm:11.1.5" "@grafana/experimental": "npm:1.7.11" - "@grafana/plugin-configs": "npm:11.1.4" - "@grafana/runtime": "npm:11.1.4" - "@grafana/schema": "npm:11.1.4" - "@grafana/ui": "npm:11.1.4" + "@grafana/plugin-configs": "npm:11.1.5" + "@grafana/runtime": "npm:11.1.5" + "@grafana/schema": "npm:11.1.5" + "@grafana/ui": "npm:11.1.5" "@kusto/monaco-kusto": "npm:^10.0.0" "@testing-library/dom": "npm:10.0.0" "@testing-library/react": "npm:15.0.2" @@ -2689,13 +2689,13 @@ __metadata: resolution: "@grafana-plugins/grafana-postgresql-datasource@workspace:public/app/plugins/datasource/grafana-postgresql-datasource" dependencies: "@emotion/css": "npm:11.11.2" - "@grafana/data": "npm:11.1.4" - "@grafana/e2e-selectors": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/e2e-selectors": "npm:11.1.5" "@grafana/experimental": "npm:1.7.11" - "@grafana/plugin-configs": "npm:11.1.4" - "@grafana/runtime": "npm:11.1.4" - "@grafana/sql": "npm:11.1.4" - "@grafana/ui": "npm:11.1.4" + "@grafana/plugin-configs": "npm:11.1.5" + "@grafana/runtime": "npm:11.1.5" + "@grafana/sql": "npm:11.1.5" + "@grafana/ui": "npm:11.1.5" "@testing-library/react": "npm:15.0.2" "@testing-library/user-event": "npm:14.5.2" "@types/jest": "npm:29.5.12" @@ -2720,11 +2720,11 @@ __metadata: resolution: "@grafana-plugins/grafana-pyroscope-datasource@workspace:public/app/plugins/datasource/grafana-pyroscope-datasource" dependencies: "@emotion/css": "npm:11.11.2" - "@grafana/data": "npm:11.1.4" - "@grafana/plugin-configs": "npm:11.1.4" - "@grafana/runtime": "npm:11.1.4" - "@grafana/schema": "npm:11.1.4" - "@grafana/ui": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/plugin-configs": "npm:11.1.5" + "@grafana/runtime": "npm:11.1.5" + "@grafana/schema": "npm:11.1.5" + "@grafana/ui": "npm:11.1.5" "@testing-library/dom": "npm:10.0.0" "@testing-library/jest-dom": "npm:6.4.2" "@testing-library/react": "npm:15.0.2" @@ -2761,13 +2761,13 @@ __metadata: resolution: "@grafana-plugins/grafana-testdata-datasource@workspace:public/app/plugins/datasource/grafana-testdata-datasource" dependencies: "@emotion/css": "npm:11.11.2" - "@grafana/data": "npm:11.1.4" - "@grafana/e2e-selectors": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/e2e-selectors": "npm:11.1.5" "@grafana/experimental": "npm:1.7.11" - "@grafana/plugin-configs": "npm:11.1.4" - "@grafana/runtime": "npm:11.1.4" - "@grafana/schema": "npm:11.1.4" - "@grafana/ui": "npm:11.1.4" + "@grafana/plugin-configs": "npm:11.1.5" + "@grafana/runtime": "npm:11.1.5" + "@grafana/schema": "npm:11.1.5" + "@grafana/ui": "npm:11.1.5" "@testing-library/dom": "npm:10.0.0" "@testing-library/react": "npm:15.0.2" "@testing-library/user-event": "npm:14.5.2" @@ -2844,13 +2844,13 @@ __metadata: resolution: "@grafana-plugins/mysql@workspace:public/app/plugins/datasource/mysql" dependencies: "@emotion/css": "npm:11.11.2" - "@grafana/data": "npm:11.1.4" - "@grafana/e2e-selectors": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/e2e-selectors": "npm:11.1.5" "@grafana/experimental": "npm:1.7.11" - "@grafana/plugin-configs": "npm:11.1.4" - "@grafana/runtime": "npm:11.1.4" - "@grafana/sql": "npm:11.1.4" - "@grafana/ui": "npm:11.1.4" + "@grafana/plugin-configs": "npm:11.1.5" + "@grafana/runtime": "npm:11.1.5" + "@grafana/sql": "npm:11.1.5" + "@grafana/ui": "npm:11.1.5" "@testing-library/react": "npm:15.0.2" "@testing-library/user-event": "npm:14.5.2" "@types/jest": "npm:29.5.12" @@ -2875,11 +2875,11 @@ __metadata: resolution: "@grafana-plugins/parca@workspace:public/app/plugins/datasource/parca" dependencies: "@emotion/css": "npm:11.11.2" - "@grafana/data": "npm:11.1.4" - "@grafana/plugin-configs": "npm:11.1.4" - "@grafana/runtime": "npm:11.1.4" - "@grafana/schema": "npm:11.1.4" - "@grafana/ui": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/plugin-configs": "npm:11.1.5" + "@grafana/runtime": "npm:11.1.5" + "@grafana/schema": "npm:11.1.5" + "@grafana/ui": "npm:11.1.5" "@testing-library/dom": "npm:10.0.0" "@testing-library/react": "npm:15.0.2" "@testing-library/user-event": "npm:14.5.2" @@ -2907,14 +2907,14 @@ __metadata: resolution: "@grafana-plugins/stackdriver@workspace:public/app/plugins/datasource/cloud-monitoring" dependencies: "@emotion/css": "npm:11.11.2" - "@grafana/data": "npm:11.1.4" - "@grafana/e2e-selectors": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/e2e-selectors": "npm:11.1.5" "@grafana/experimental": "npm:1.7.11" "@grafana/google-sdk": "npm:0.1.2" - "@grafana/plugin-configs": "npm:11.1.4" - "@grafana/runtime": "npm:11.1.4" - "@grafana/schema": "npm:11.1.4" - "@grafana/ui": "npm:11.1.4" + "@grafana/plugin-configs": "npm:11.1.5" + "@grafana/runtime": "npm:11.1.5" + "@grafana/schema": "npm:11.1.5" + "@grafana/ui": "npm:11.1.5" "@testing-library/dom": "npm:10.0.0" "@testing-library/react": "npm:15.0.2" "@testing-library/user-event": "npm:14.5.2" @@ -2962,7 +2962,7 @@ __metadata: "@grafana/lezer-traceql": "npm:0.0.17" "@grafana/monaco-logql": "npm:^0.0.7" "@grafana/o11y-ds-frontend": "workspace:*" - "@grafana/plugin-configs": "npm:11.1.4" + "@grafana/plugin-configs": "npm:11.1.5" "@grafana/runtime": "workspace:*" "@grafana/schema": "workspace:*" "@grafana/ui": "workspace:*" @@ -3072,12 +3072,12 @@ __metadata: languageName: node linkType: hard -"@grafana/data@npm:11.1.4, @grafana/data@workspace:*, @grafana/data@workspace:packages/grafana-data": +"@grafana/data@npm:11.1.5, @grafana/data@workspace:*, @grafana/data@workspace:packages/grafana-data": version: 0.0.0-use.local resolution: "@grafana/data@workspace:packages/grafana-data" dependencies: "@braintree/sanitize-url": "npm:7.0.1" - "@grafana/schema": "npm:11.1.4" + "@grafana/schema": "npm:11.1.5" "@grafana/tsconfig": "npm:^1.3.0-rc1" "@rollup/plugin-node-resolve": "npm:15.2.3" "@types/d3-interpolate": "npm:^3.0.0" @@ -3125,7 +3125,7 @@ __metadata: languageName: unknown linkType: soft -"@grafana/e2e-selectors@npm:11.1.4, @grafana/e2e-selectors@npm:^11.0.0, @grafana/e2e-selectors@workspace:*, @grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors": +"@grafana/e2e-selectors@npm:11.1.5, @grafana/e2e-selectors@npm:^11.0.0, @grafana/e2e-selectors@workspace:*, @grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors": version: 0.0.0-use.local resolution: "@grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors" dependencies: @@ -3250,9 +3250,9 @@ __metadata: "@babel/preset-env": "npm:7.24.7" "@babel/preset-react": "npm:7.24.7" "@emotion/css": "npm:11.11.2" - "@grafana/data": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" "@grafana/tsconfig": "npm:^1.3.0-rc1" - "@grafana/ui": "npm:11.1.4" + "@grafana/ui": "npm:11.1.5" "@leeoniya/ufuzzy": "npm:1.0.14" "@rollup/plugin-node-resolve": "npm:15.2.3" "@testing-library/dom": "npm:10.0.0" @@ -3334,13 +3334,13 @@ __metadata: resolution: "@grafana/o11y-ds-frontend@workspace:packages/grafana-o11y-ds-frontend" dependencies: "@emotion/css": "npm:11.11.2" - "@grafana/data": "npm:11.1.4" - "@grafana/e2e-selectors": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/e2e-selectors": "npm:11.1.5" "@grafana/experimental": "npm:1.7.11" - "@grafana/runtime": "npm:11.1.4" - "@grafana/schema": "npm:11.1.4" + "@grafana/runtime": "npm:11.1.5" + "@grafana/schema": "npm:11.1.5" "@grafana/tsconfig": "npm:^1.3.0-rc1" - "@grafana/ui": "npm:11.1.4" + "@grafana/ui": "npm:11.1.5" "@testing-library/dom": "npm:10.0.0" "@testing-library/jest-dom": "npm:^6.1.2" "@testing-library/react": "npm:15.0.2" @@ -3365,7 +3365,7 @@ __metadata: languageName: unknown linkType: soft -"@grafana/plugin-configs@npm:11.1.4, @grafana/plugin-configs@workspace:*, @grafana/plugin-configs@workspace:packages/grafana-plugin-configs": +"@grafana/plugin-configs@npm:11.1.5, @grafana/plugin-configs@workspace:*, @grafana/plugin-configs@workspace:packages/grafana-plugin-configs": version: 0.0.0-use.local resolution: "@grafana/plugin-configs@workspace:packages/grafana-plugin-configs" dependencies: @@ -3405,14 +3405,14 @@ __metadata: "@emotion/css": "npm:11.11.2" "@emotion/eslint-plugin": "npm:11.11.0" "@floating-ui/react": "npm:0.26.16" - "@grafana/data": "npm:11.1.4" - "@grafana/e2e-selectors": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/e2e-selectors": "npm:11.1.5" "@grafana/experimental": "npm:1.7.11" "@grafana/faro-web-sdk": "npm:1.7.3" - "@grafana/runtime": "npm:11.1.4" - "@grafana/schema": "npm:11.1.4" + "@grafana/runtime": "npm:11.1.5" + "@grafana/schema": "npm:11.1.5" "@grafana/tsconfig": "npm:^1.3.0-rc1" - "@grafana/ui": "npm:11.1.4" + "@grafana/ui": "npm:11.1.5" "@leeoniya/ufuzzy": "npm:1.0.14" "@lezer/common": "npm:1.2.1" "@lezer/highlight": "npm:1.2.0" @@ -3510,16 +3510,16 @@ __metadata: languageName: unknown linkType: soft -"@grafana/runtime@npm:11.1.4, @grafana/runtime@workspace:*, @grafana/runtime@workspace:packages/grafana-runtime": +"@grafana/runtime@npm:11.1.5, @grafana/runtime@workspace:*, @grafana/runtime@workspace:packages/grafana-runtime": version: 0.0.0-use.local resolution: "@grafana/runtime@workspace:packages/grafana-runtime" dependencies: - "@grafana/data": "npm:11.1.4" - "@grafana/e2e-selectors": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/e2e-selectors": "npm:11.1.5" "@grafana/faro-web-sdk": "npm:^1.3.6" - "@grafana/schema": "npm:11.1.4" + "@grafana/schema": "npm:11.1.5" "@grafana/tsconfig": "npm:^1.3.0-rc1" - "@grafana/ui": "npm:11.1.4" + "@grafana/ui": "npm:11.1.5" "@rollup/plugin-node-resolve": "npm:15.2.3" "@rollup/plugin-terser": "npm:0.4.4" "@testing-library/dom": "npm:10.0.0" @@ -3608,7 +3608,7 @@ __metadata: languageName: node linkType: hard -"@grafana/schema@npm:11.1.4, @grafana/schema@workspace:*, @grafana/schema@workspace:packages/grafana-schema": +"@grafana/schema@npm:11.1.5, @grafana/schema@workspace:*, @grafana/schema@workspace:packages/grafana-schema": version: 0.0.0-use.local resolution: "@grafana/schema@workspace:packages/grafana-schema" dependencies: @@ -3626,17 +3626,17 @@ __metadata: languageName: unknown linkType: soft -"@grafana/sql@npm:11.1.4, @grafana/sql@workspace:*, @grafana/sql@workspace:packages/grafana-sql": +"@grafana/sql@npm:11.1.5, @grafana/sql@workspace:*, @grafana/sql@workspace:packages/grafana-sql": version: 0.0.0-use.local resolution: "@grafana/sql@workspace:packages/grafana-sql" dependencies: "@emotion/css": "npm:11.11.2" - "@grafana/data": "npm:11.1.4" - "@grafana/e2e-selectors": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/e2e-selectors": "npm:11.1.5" "@grafana/experimental": "npm:1.7.11" - "@grafana/runtime": "npm:11.1.4" + "@grafana/runtime": "npm:11.1.5" "@grafana/tsconfig": "npm:^1.3.0-rc1" - "@grafana/ui": "npm:11.1.4" + "@grafana/ui": "npm:11.1.5" "@react-awesome-query-builder/ui": "npm:6.5.2" "@testing-library/dom": "npm:10.0.0" "@testing-library/jest-dom": "npm:^6.1.2" @@ -3679,7 +3679,7 @@ __metadata: languageName: node linkType: hard -"@grafana/ui@npm:11.1.4, @grafana/ui@workspace:*, @grafana/ui@workspace:packages/grafana-ui": +"@grafana/ui@npm:11.1.5, @grafana/ui@workspace:*, @grafana/ui@workspace:packages/grafana-ui": version: 0.0.0-use.local resolution: "@grafana/ui@workspace:packages/grafana-ui" dependencies: @@ -3688,10 +3688,10 @@ __metadata: "@emotion/react": "npm:11.11.4" "@faker-js/faker": "npm:^8.4.1" "@floating-ui/react": "npm:0.26.16" - "@grafana/data": "npm:11.1.4" - "@grafana/e2e-selectors": "npm:11.1.4" + "@grafana/data": "npm:11.1.5" + "@grafana/e2e-selectors": "npm:11.1.5" "@grafana/faro-web-sdk": "npm:^1.3.6" - "@grafana/schema": "npm:11.1.4" + "@grafana/schema": "npm:11.1.5" "@grafana/tsconfig": "npm:^1.3.0-rc1" "@leeoniya/ufuzzy": "npm:1.0.14" "@monaco-editor/react": "npm:4.6.0"