mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
SQL Datasources: Update Max Connection and Max Idle Connection Defaults to 100 and add auto mode (#65834)
* Update connection configuration for SQL datasources * Working auto state for connection numbers * Add migration * Use defaults from constants file * Remove dead code * Add tests and restructure useMigrateDatabaseField * Update function names * Update docs * Make sure we don't continually issue updates * Update docs * Use onOptionsChnage in ConnectionLimits * Update docs * Clean up docs * Update migration * Fix default values in docs * Fix spacing issue * Fix test * Update default values for SQL connections * Include consts * Allow override for default SQL datasource connection parameters * Fix linter errors * Remove extra @ts-ignore * Centralize logic for default values * Remove debugging * Remove unecessary function * Update configuration docs * minor suggested change * Fix comment misspelling * Remove unecessary default setting code * Update docs to indicate that code was included for backport version * Remove dead code --------- Co-authored-by: lwandz13 <larissa.wandzura@grafana.com>
This commit is contained in:
parent
2509dec0cb
commit
92d92187d9
@ -413,6 +413,21 @@ default_home_dashboard_path =
|
||||
# Upper limit of data sources that Grafana will return. This limit is a temporary configuration and it will be deprecated when pagination will be introduced on the list data sources API.
|
||||
datasource_limit = 5000
|
||||
|
||||
|
||||
################################### SQL Data Sources #####################
|
||||
[sql_datasources]
|
||||
# Default maximum number of open connections maintained in the connection pool
|
||||
# when connecting to SQL based data sources
|
||||
max_open_conns_default = 100
|
||||
|
||||
# Default maximum number of idle connections maintained in the connection pool
|
||||
# when connecting to SQL based data sources
|
||||
max_idle_conns_default = 100
|
||||
|
||||
# Default maximum connection lifetime used when connecting
|
||||
# to SQL based data sources.
|
||||
max_conn_lifetime_default = 14400
|
||||
|
||||
#################################### Users ###############################
|
||||
[users]
|
||||
# disable user signup / registration
|
||||
|
@ -41,19 +41,20 @@ To configure basic settings for the data source, complete the following steps:
|
||||
|
||||
1. Set the data source's basic configuration options:
|
||||
|
||||
| Name | Description |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Name** | Sets the name you use to refer to the data source in panels and queries. |
|
||||
| **Default** | Sets the data source that's pre-selected for new panels. |
|
||||
| **Host** | Sets the IP address/hostname and optional port of your MS SQL instance. Default port is 0, the driver default. You can specify multiple connection properties, such as `ApplicationIntent`, by separating each property with a semicolon (`;`). |
|
||||
| **Database** | Sets the name of your MS SQL database. |
|
||||
| **Authentication** | Sets the authentication mode, either using SQL Server Authentication or Windows Authentication (single sign-on for Windows users). |
|
||||
| **User** | Defines the database user's username. |
|
||||
| **Password** | Defines the database user's password. |
|
||||
| **Encrypt** | Determines whether to negotiate a secure SSL TCP/IP connection with the server, or to which extent. Default is `false`. |
|
||||
| **Max open** | Sets the maximum number of open connections to the database. Default is `unlimited`. |
|
||||
| **Max idle** | Sets the maximum number of connections in the idle connection pool. Default is `2`. |
|
||||
| **Max lifetime** | Sets the maximum number of seconds that the data source can reuse a connection. Default is `14400` (4 hours). |
|
||||
| Name | Description |
|
||||
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Name** | Sets the name you use to refer to the data source in panels and queries. |
|
||||
| **Default** | Sets the data source that's pre-selected for new panels. |
|
||||
| **Host** | Sets the IP address/hostname and optional port of your MS SQL instance. Default port is 0, the driver default. You can specify multiple connection properties, such as `ApplicationIntent`, by separating each property with a semicolon (`;`). |
|
||||
| **Database** | Sets the name of your MS SQL database. |
|
||||
| **Authentication** | Sets the authentication mode, either using SQL Server Authentication or Windows Authentication (single sign-on for Windows users). |
|
||||
| **User** | Defines the database user's username. |
|
||||
| **Password** | Defines the database user's password. |
|
||||
| **Encrypt** | Determines whether to negotiate a secure SSL TCP/IP connection with the server, or to which extent. Default is `false`. |
|
||||
| **Max open** | Sets the maximum number of open connections to the database. Default is `100`. |
|
||||
| **Max idle** | Sets the maximum number of connections in the idle connection pool. Default is `100`. |
|
||||
| **Auto (max idle)** | If set will set the maximum number of idle connections to the number of maximum open connections (Grafana v9.5.1+). Default is `true`. |
|
||||
| **Max lifetime** | Sets the maximum number of seconds that the data source can reuse a connection. Default is `14400` (4 hours). |
|
||||
|
||||
You can also configure settings specific to the Microsoft SQL Server data source. These options are described in the sections below.
|
||||
|
||||
@ -122,8 +123,9 @@ datasources:
|
||||
user: grafana
|
||||
jsonData:
|
||||
database: grafana
|
||||
maxOpenConns: 0 # Grafana v5.4+
|
||||
maxIdleConns: 2 # Grafana v5.4+
|
||||
maxOpenConns: 100 # Grafana v5.4+
|
||||
maxIdleConns: 100 # Grafana v5.4+
|
||||
maxIdleConnsAuto: true # Grafana v9.5.1+
|
||||
connMaxLifetime: 14400 # Grafana v5.4+
|
||||
connectionTimeout: 0 # Grafana v9.3+
|
||||
secureJsonData:
|
||||
|
@ -35,20 +35,19 @@ Administrators can also [configure the data source via YAML]({{< relref "#provis
|
||||
|
||||
1. Set the data source's basic configuration options.
|
||||
|
||||
### Data source options
|
||||
|
||||
| Name | Description |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `Name` | The data source name. This is how you refer to the data source in panels and queries. |
|
||||
| `Default` | Default data source means that it will be pre-selected for new panels. |
|
||||
| `Host` | The IP address/hostname and optional port of your MySQL instance. |
|
||||
| `Database` | Name of your MySQL database. |
|
||||
| `User` | Database user's login/username |
|
||||
| `Password` | Database user's password |
|
||||
| `Session Timezone` | Specify the time zone used in the database session, such as `Europe/Berlin` or `+02:00`. This is necessary, if the timezone of the database (or the host of the database) is set to something other than UTC. Set the value used in the session with `SET time_zone='...'`. If you leave this field empty, then the time zone is not updated. For more information, refer to the [MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html). |
|
||||
| `Max open` | The maximum number of open connections to the database, default `unlimited` (Grafana v5.4+). |
|
||||
| `Max idle` | The maximum number of connections in the idle connection pool, default `2` (Grafana v5.4+). |
|
||||
| `Max lifetime` | The maximum amount of time in seconds a connection may be reused, default `14400`/4 hours. This should always be lower than configured [wait_timeout](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_wait_timeout) in MySQL (Grafana v5.4+). |
|
||||
| Name | Description |
|
||||
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Name** | The data source name. This is how you refer to the data source in panels and queries. |
|
||||
| **Default** | Default data source means that it will be pre-selected for new panels. |
|
||||
| **Host** | The IP address/hostname and optional port of your MySQL instance. |
|
||||
| **Database** | Name of your MySQL database. |
|
||||
| **User** | Database user's login/username |
|
||||
| **Password** | Database user's password |
|
||||
| **Session Timezone** | Specify the time zone used in the database session, such as `Europe/Berlin` or `+02:00`. This is necessary, if the timezone of the database (or the host of the database) is set to something other than UTC. Set the value used in the session with `SET time_zone='...'`. If you leave this field empty, then the time zone is not updated. For more information, refer to the [MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html). |
|
||||
| **Max open** | The maximum number of open connections to the database, default `100` (Grafana v5.4+). |
|
||||
| **Max idle** | The maximum number of connections in the idle connection pool, default `100` (Grafana v5.4+). |
|
||||
| **Auto (max idle)** | If set will set the maximum number of idle connections to the number of maximum open connections (Grafana v9.5.1+). Default is `true`. |
|
||||
| **Max lifetime** | The maximum amount of time in seconds a connection may be reused, default `14400`/4 hours. This should always be lower than configured [wait_timeout](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_wait_timeout) in MySQL (Grafana v5.4+). |
|
||||
|
||||
### Min time interval
|
||||
|
||||
@ -107,8 +106,9 @@ datasources:
|
||||
user: grafana
|
||||
jsonData:
|
||||
database: grafana
|
||||
maxOpenConns: 0 # Grafana v5.4+
|
||||
maxIdleConns: 2 # Grafana v5.4+
|
||||
maxOpenConns: 100 # Grafana v5.4+
|
||||
maxIdleConns: 100 # Grafana v5.4+
|
||||
maxIdleConnsAuto: true # Grafana v9.5.1+
|
||||
connMaxLifetime: 14400 # Grafana v5.4+
|
||||
secureJsonData:
|
||||
password: ${GRAFANA_MYSQL_PASSWORD}
|
||||
@ -127,8 +127,9 @@ datasources:
|
||||
jsonData:
|
||||
tlsAuth: true
|
||||
database: grafana
|
||||
maxOpenConns: 0 # Grafana v5.4+
|
||||
maxIdleConns: 2 # Grafana v5.4+
|
||||
maxOpenConns: 100 # Grafana v5.4+
|
||||
maxIdleConns: 100 # Grafana v5.4+
|
||||
maxIdleConnsAuto: true # Grafana v9.5.1+
|
||||
connMaxLifetime: 14400 # Grafana v5.4+
|
||||
secureJsonData:
|
||||
password: ${GRAFANA_MYSQL_PASSWORD}
|
||||
@ -150,8 +151,9 @@ datasources:
|
||||
tlsAuth: true
|
||||
skipTLSVerify: true
|
||||
database: grafana
|
||||
maxOpenConns: 0 # Grafana v5.4+
|
||||
maxIdleConns: 2 # Grafana v5.4+
|
||||
maxOpenConns: 100 # Grafana v5.4+
|
||||
maxIdleConns: 100 # Grafana v5.4+
|
||||
maxIdleConnsAuto: true # Grafana v9.5.1+
|
||||
connMaxLifetime: 14400 # Grafana v5.4+
|
||||
secureJsonData:
|
||||
password: ${GRAFANA_MYSQL_PASSWORD}
|
||||
|
@ -33,23 +33,23 @@ To configure basic settings for the data source, complete the following steps:
|
||||
|
||||
1. Set the data source's basic configuration options:
|
||||
|
||||
| Name | Description |
|
||||
|
||||
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Name** | The data source name. This is how you refer to the data source in panels and queries. |
|
||||
| **Default** | Default data source means that it will be pre-selected for new panels. |
|
||||
| **Host** | The IP address/hostname and optional port of your PostgreSQL instance. _Do not_ include the database name. The connection string for connecting to Postgres will not be correct and it may cause errors. |
|
||||
| **Database** | Name of your PostgreSQL database. |
|
||||
| **User** | Database user's login/username |
|
||||
| **Password** | Database user's password |
|
||||
| **SSL Mode** | Determines whether or with what priority a secure SSL TCP/IP connection will be negotiated with the server. When SSL Mode is disabled, SSL Method and Auth Details would not be visible. |
|
||||
| **SSL Auth Details Method** | Determines whether the SSL Auth details will be configured as a file path or file content. Grafana v7.5+ |
|
||||
| **SSL Auth Details Value** | File path or file content of SSL root certificate, client certificate and client key |
|
||||
| **Max open** | The maximum number of open connections to the database, default `unlimited` (Grafana v5.4+). |
|
||||
| **Max idle** | The maximum number of connections in the idle connection pool, default `2` (Grafana v5.4+). |
|
||||
| **Max lifetime** | The maximum amount of time in seconds a connection may be reused, default `14400`/4 hours (Grafana v5.4+). |
|
||||
| **Version** | Determines which functions are available in the query builder (only available in Grafana 5.3+). |
|
||||
| **TimescaleDB** | A time-series database built as a PostgreSQL extension. When enabled, Grafana uses `time_bucket` in the `$__timeGroup` macro to display TimescaleDB specific aggregate functions in the query builder (only available in Grafana 5.3+). For more information, see [TimescaleDB documentation](https://docs.timescale.com/timescaledb/latest/tutorials/grafana/grafana-timescalecloud/#connect-timescaledb-and-grafana). |
|
||||
| Name | Description |
|
||||
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Name** | The data source name. This is how you refer to the data source in panels and queries. |
|
||||
| **Default** | Default data source means that it will be pre-selected for new panels. |
|
||||
| **Host** | The IP address/hostname and optional port of your PostgreSQL instance. _Do not_ include the database name. The connection string for connecting to Postgres will not be correct and it may cause errors. |
|
||||
| **Database** | Name of your PostgreSQL database. |
|
||||
| **User** | Database user's login/username |
|
||||
| **Password** | Database user's password |
|
||||
| **SSL Mode** | Determines whether or with what priority a secure SSL TCP/IP connection will be negotiated with the server. When SSL Mode is disabled, SSL Method and Auth Details would not be visible. |
|
||||
| **SSL Auth Details Method** | Determines whether the SSL Auth details will be configured as a file path or file content. Grafana v7.5+ |
|
||||
| **SSL Auth Details Value** | File path or file content of SSL root certificate, client certificate and client key |
|
||||
| **Max open** | The maximum number of open connections to the database, default `100` (Grafana v5.4+). |
|
||||
| **Max idle** | The maximum number of connections in the idle connection pool, default `100` (Grafana v5.4+). |
|
||||
| **Auto (max idle)** | If set will set the maximum number of idle connections to the number of maximum open connections (Grafana v9.5.1+). Default is `true`. |
|
||||
| **Max lifetime** | The maximum amount of time in seconds a connection may be reused, default `14400`/4 hours (Grafana v5.4+). |
|
||||
| **Version** | Determines which functions are available in the query builder (only available in Grafana 5.3+). |
|
||||
| **TimescaleDB** | A time-series database built as a PostgreSQL extension. When enabled, Grafana uses `time_bucket` in the `$__timeGroup` macro to display TimescaleDB specific aggregate functions in the query builder (only available in Grafana 5.3+). For more information, see [TimescaleDB documentation](https://docs.timescale.com/timescaledb/latest/tutorials/grafana/grafana-timescalecloud/#connect-timescaledb-and-grafana). |
|
||||
|
||||
### Min time interval
|
||||
|
||||
@ -141,8 +141,9 @@ datasources:
|
||||
jsonData:
|
||||
database: grafana
|
||||
sslmode: 'disable' # disable/require/verify-ca/verify-full
|
||||
maxOpenConns: 0 # Grafana v5.4+
|
||||
maxIdleConns: 2 # Grafana v5.4+
|
||||
maxOpenConns: 100 # Grafana v5.4+
|
||||
maxIdleConns: 100 # Grafana v5.4+
|
||||
maxIdleConnsAuto: true # Grafana v9.5.1+
|
||||
connMaxLifetime: 14400 # Grafana v5.4+
|
||||
postgresVersion: 903 # 903=9.3, 904=9.4, 905=9.5, 906=9.6, 1000=10
|
||||
timescaledb: false
|
||||
|
@ -75,7 +75,7 @@ rendering_ignore_https_errors = true
|
||||
enable = newNavigation
|
||||
```
|
||||
|
||||
You can override them on Linux machines with:
|
||||
You can override variables on Linux machines with:
|
||||
|
||||
```bash
|
||||
export GF_DEFAULT_INSTANCE_NAME=my-instance
|
||||
@ -730,6 +730,22 @@ Path to the default home dashboard. If this value is empty, then Grafana uses St
|
||||
|
||||
<hr />
|
||||
|
||||
## [sql_datasources]
|
||||
|
||||
### max_open_conns_default
|
||||
|
||||
For SQL data sources (MySql, Postgres, MSSQL) you can override the default maximum number of open connections (default: 100). The value configured in data source settings will be preferred over the default value.
|
||||
|
||||
### max_idle_conns_default
|
||||
|
||||
For SQL data sources (MySql, Postgres, MSSQL) you can override the default allowed number of idle connections (default: 100). The value configured in data source settings will be preferred over the default value.
|
||||
|
||||
### max_conn_lifetime_default
|
||||
|
||||
For SQL data sources (MySql, Postgres, MSSQL) you can override the default maximum connection lifetime specified in seconds (default: 14400). The value configured in data source settings will be preferred over the default value.
|
||||
|
||||
<hr/>
|
||||
|
||||
## [users]
|
||||
|
||||
### allow_sign_up
|
||||
|
@ -369,6 +369,11 @@ type Cfg struct {
|
||||
// Data sources
|
||||
DataSourceLimit int
|
||||
|
||||
// SQL Data sources
|
||||
SqlDatasourceMaxOpenConnsDefault int
|
||||
SqlDatasourceMaxIdleConnsDefault int
|
||||
SqlDatasourceMaxConnLifetimeDefault int
|
||||
|
||||
// Snapshots
|
||||
SnapshotEnabled bool
|
||||
ExternalSnapshotUrl string
|
||||
@ -1116,6 +1121,7 @@ func (cfg *Cfg) Load(args CommandLineArgs) error {
|
||||
}
|
||||
|
||||
cfg.readDataSourcesSettings()
|
||||
cfg.readSqlDataSourceSettings()
|
||||
|
||||
cfg.Storage = readStorageSettings(iniFile)
|
||||
cfg.Search = readSearchSettings(iniFile)
|
||||
@ -1848,6 +1854,13 @@ func (cfg *Cfg) readDataSourcesSettings() {
|
||||
cfg.DataSourceLimit = datasources.Key("datasource_limit").MustInt(5000)
|
||||
}
|
||||
|
||||
func (cfg *Cfg) readSqlDataSourceSettings() {
|
||||
sqlDatasources := cfg.Raw.Section("sql_datasources")
|
||||
cfg.SqlDatasourceMaxOpenConnsDefault = sqlDatasources.Key("max_open_conns_default").MustInt(100)
|
||||
cfg.SqlDatasourceMaxIdleConnsDefault = sqlDatasources.Key("max_idle_conns_default").MustInt(100)
|
||||
cfg.SqlDatasourceMaxConnLifetimeDefault = sqlDatasources.Key("max_conn_lifetime_default").MustInt(14400)
|
||||
}
|
||||
|
||||
func GetAllowedOriginGlobs(originPatterns []string) ([]glob.Glob, error) {
|
||||
allowedOrigins := originPatterns
|
||||
originGlobs := make([]glob.Glob, 0, len(allowedOrigins))
|
||||
|
@ -56,9 +56,9 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
||||
func newInstanceSettings(cfg *setting.Cfg) datasource.InstanceFactoryFunc {
|
||||
return func(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
||||
jsonData := sqleng.JsonData{
|
||||
MaxOpenConns: 0,
|
||||
MaxIdleConns: 2,
|
||||
ConnMaxLifetime: 14400,
|
||||
MaxOpenConns: cfg.SqlDatasourceMaxOpenConnsDefault,
|
||||
MaxIdleConns: cfg.SqlDatasourceMaxIdleConnsDefault,
|
||||
ConnMaxLifetime: cfg.SqlDatasourceMaxConnLifetimeDefault,
|
||||
Encrypt: "false",
|
||||
ConnectionTimeout: 0,
|
||||
SecureDSProxy: false,
|
||||
|
@ -52,9 +52,9 @@ func ProvideService(cfg *setting.Cfg, httpClientProvider httpclient.Provider) *S
|
||||
func newInstanceSettings(cfg *setting.Cfg, httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
|
||||
return func(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
||||
jsonData := sqleng.JsonData{
|
||||
MaxOpenConns: 0,
|
||||
MaxIdleConns: 2,
|
||||
ConnMaxLifetime: 14400,
|
||||
MaxOpenConns: cfg.SqlDatasourceMaxOpenConnsDefault,
|
||||
MaxIdleConns: cfg.SqlDatasourceMaxIdleConnsDefault,
|
||||
ConnMaxLifetime: cfg.SqlDatasourceMaxConnLifetimeDefault,
|
||||
SecureDSProxy: false,
|
||||
}
|
||||
|
||||
|
@ -56,9 +56,9 @@ func (s *Service) newInstanceSettings(cfg *setting.Cfg) datasource.InstanceFacto
|
||||
return func(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
||||
logger.Debug("Creating Postgres query endpoint")
|
||||
jsonData := sqleng.JsonData{
|
||||
MaxOpenConns: 0,
|
||||
MaxIdleConns: 2,
|
||||
ConnMaxLifetime: 14400,
|
||||
MaxOpenConns: cfg.SqlDatasourceMaxOpenConnsDefault,
|
||||
MaxIdleConns: cfg.SqlDatasourceMaxIdleConnsDefault,
|
||||
ConnMaxLifetime: cfg.SqlDatasourceMaxConnLifetimeDefault,
|
||||
Timescaledb: false,
|
||||
ConfigurationMethod: "file-path",
|
||||
SecureDSProxy: false,
|
||||
|
@ -84,6 +84,13 @@ type DataSourceInfo struct {
|
||||
DecryptedSecureJSONData map[string]string
|
||||
}
|
||||
|
||||
// Defaults for the xorm connection pool
|
||||
type DefaultConnectionInfo struct {
|
||||
MaxOpenConns int
|
||||
MaxIdleConns int
|
||||
ConnMaxLifetime int
|
||||
}
|
||||
|
||||
type DataPluginConfiguration struct {
|
||||
DriverName string
|
||||
DSInfo DataSourceInfo
|
||||
|
@ -11,6 +11,8 @@ interface Props {
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
width?: number;
|
||||
fieldDisabled?: boolean;
|
||||
}
|
||||
|
||||
interface State {
|
||||
@ -107,6 +109,8 @@ export class NumberInput extends PureComponent<Props, State> {
|
||||
onBlur={this.updateValue}
|
||||
onKeyPress={this.onKeyPress}
|
||||
placeholder={this.props.placeholder}
|
||||
disabled={this.props.fieldDisabled}
|
||||
width={this.props.width}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -1,27 +1,86 @@
|
||||
import React from 'react';
|
||||
|
||||
import { FieldSet, InlineField } from '@grafana/ui';
|
||||
import { DataSourceSettings } from '@grafana/data';
|
||||
import { FieldSet, InlineField, InlineFieldRow, InlineSwitch } from '@grafana/ui';
|
||||
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
|
||||
|
||||
import { SQLConnectionLimits } from '../../types';
|
||||
import { SQLConnectionDefaults } from '../../constants';
|
||||
import { SQLConnectionLimits, SQLOptions } from '../../types';
|
||||
|
||||
interface Props<T> {
|
||||
onPropertyChanged: (property: keyof T, value?: number) => void;
|
||||
onOptionsChange: Function;
|
||||
options: DataSourceSettings<SQLOptions>;
|
||||
labelWidth: number;
|
||||
jsonData: SQLConnectionLimits;
|
||||
}
|
||||
|
||||
export const ConnectionLimits = <T extends SQLConnectionLimits>(props: Props<T>) => {
|
||||
const { onPropertyChanged, labelWidth, jsonData } = props;
|
||||
const { onOptionsChange, options, labelWidth } = props;
|
||||
const jsonData = options.jsonData;
|
||||
const autoIdle = jsonData.maxIdleConnsAuto !== undefined ? jsonData.maxIdleConnsAuto : false;
|
||||
|
||||
// Update JSON data with new values
|
||||
const updateJsonData = (values: {}) => {
|
||||
const newOpts = {
|
||||
...options,
|
||||
jsonData: {
|
||||
...jsonData,
|
||||
...values,
|
||||
},
|
||||
};
|
||||
|
||||
return onOptionsChange(newOpts);
|
||||
};
|
||||
|
||||
// For the case of idle connections and connection lifetime
|
||||
// use a shared function to update respective properties
|
||||
const onJSONDataNumberChanged = (property: keyof SQLConnectionLimits) => {
|
||||
return (number?: number) => {
|
||||
if (onPropertyChanged) {
|
||||
onPropertyChanged(property, number);
|
||||
}
|
||||
updateJsonData({ property: number });
|
||||
};
|
||||
};
|
||||
|
||||
// When the maximum number of connections is changed
|
||||
// see if we have the automatic idle option enabled
|
||||
const onMaxConnectionsChanged = (number?: number) => {
|
||||
if (autoIdle && number) {
|
||||
updateJsonData({
|
||||
maxOpenConns: number,
|
||||
maxIdleConns: number,
|
||||
});
|
||||
} else if (number !== undefined) {
|
||||
updateJsonData({
|
||||
maxOpenConns: number,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Update auto idle setting when control is toggled
|
||||
// and set minimum idle connections if automatic
|
||||
// is selected
|
||||
const onConnectionIdleAutoChanged = () => {
|
||||
let idleConns = undefined;
|
||||
let maxConns = undefined;
|
||||
|
||||
// If the maximum number of open connections is undefined
|
||||
// and we're setting auto idle then set the default amount
|
||||
// otherwise take the numeric amount and get the value from that
|
||||
if (!autoIdle) {
|
||||
if (jsonData.maxOpenConns !== undefined) {
|
||||
maxConns = jsonData.maxOpenConns;
|
||||
idleConns = jsonData.maxOpenConns;
|
||||
} else {
|
||||
maxConns = SQLConnectionDefaults.MAX_CONNS;
|
||||
idleConns = SQLConnectionDefaults.MAX_CONNS;
|
||||
}
|
||||
}
|
||||
|
||||
updateJsonData({
|
||||
maxIdleConnsAuto: !autoIdle,
|
||||
maxIdleConns: idleConns,
|
||||
maxOpenConns: maxConns,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<FieldSet label="Connection limits">
|
||||
<InlineField
|
||||
@ -36,29 +95,42 @@ export const ConnectionLimits = <T extends SQLConnectionLimits>(props: Props<T>)
|
||||
labelWidth={labelWidth}
|
||||
label="Max open"
|
||||
>
|
||||
<NumberInput
|
||||
placeholder="unlimited"
|
||||
value={jsonData.maxOpenConns}
|
||||
onChange={onJSONDataNumberChanged('maxOpenConns')}
|
||||
></NumberInput>
|
||||
</InlineField>
|
||||
<InlineField
|
||||
tooltip={
|
||||
<span>
|
||||
The maximum number of connections in the idle connection pool.If <i>Max open connections</i> is greater than
|
||||
0 but less than the <i>Max idle connections</i>, then the <i>Max idle connections</i> will be reduced to
|
||||
match the <i>Max open connections</i> limit. If set to 0, no idle connections are retained.
|
||||
</span>
|
||||
}
|
||||
labelWidth={labelWidth}
|
||||
label="Max idle"
|
||||
>
|
||||
<NumberInput
|
||||
placeholder="2"
|
||||
value={jsonData.maxIdleConns}
|
||||
onChange={onJSONDataNumberChanged('maxIdleConns')}
|
||||
></NumberInput>
|
||||
<NumberInput placeholder="unlimited" value={jsonData.maxOpenConns} onChange={onMaxConnectionsChanged} />
|
||||
</InlineField>
|
||||
<InlineFieldRow>
|
||||
<InlineField
|
||||
tooltip={
|
||||
<span>
|
||||
The maximum number of connections in the idle connection pool.If <i>Max open connections</i> is greater
|
||||
than 0 but less than the <i>Max idle connections</i>, then the <i>Max idle connections</i> will be reduced
|
||||
to match the <i>Max open connections</i> limit. If set to 0, no idle connections are retained.
|
||||
</span>
|
||||
}
|
||||
labelWidth={labelWidth}
|
||||
label="Max idle"
|
||||
>
|
||||
<NumberInput
|
||||
placeholder="2"
|
||||
value={jsonData.maxIdleConns}
|
||||
onChange={onJSONDataNumberChanged('maxIdleConns')}
|
||||
width={8}
|
||||
fieldDisabled={autoIdle}
|
||||
/>
|
||||
</InlineField>
|
||||
<InlineField
|
||||
label="Auto"
|
||||
labelWidth={8}
|
||||
tooltip={
|
||||
<span>
|
||||
If enabled, automatically set the number of <i>Maximum idle connections</i> to the same value as
|
||||
<i> Max open connections</i>. If the number of maximum open connections is not set it will be set to the
|
||||
default ({SQLConnectionDefaults.MAX_CONNS}).
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<InlineSwitch value={autoIdle} onChange={onConnectionIdleAutoChanged} />
|
||||
</InlineField>
|
||||
</InlineFieldRow>
|
||||
<InlineField
|
||||
tooltip="The maximum amount of time in seconds a connection may be reused. If set to 0, connections are reused forever."
|
||||
labelWidth={labelWidth}
|
||||
|
@ -1,25 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { DataSourceJsonData, DataSourcePluginOptionsEditorProps } from '@grafana/data';
|
||||
import { logDebug } from '@grafana/runtime';
|
||||
|
||||
import { SQLOptions } from '../../types';
|
||||
|
||||
/**
|
||||
* Moves the database field from the options object to jsonData.database and empties the database field.
|
||||
*/
|
||||
export function useMigrateDatabaseField<T extends DataSourceJsonData = SQLOptions, S = {}>({
|
||||
onOptionsChange,
|
||||
options,
|
||||
}: DataSourcePluginOptionsEditorProps<T, S>) {
|
||||
useEffect(() => {
|
||||
if (options.database) {
|
||||
logDebug(`Migrating from options.database with value ${options.database} for ${options.name}`);
|
||||
onOptionsChange({
|
||||
...options,
|
||||
database: '',
|
||||
jsonData: { ...options.jsonData, database: options.database },
|
||||
});
|
||||
}
|
||||
}, [onOptionsChange, options]);
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
|
||||
import { DataSourceSettings } from '@grafana/data';
|
||||
|
||||
import { SQLConnectionDefaults } from '../../constants';
|
||||
import { SQLOptions } from '../../types';
|
||||
|
||||
import { useMigrateDatabaseFields } from './useMigrateDatabaseFields';
|
||||
|
||||
describe('Database Field Migration', () => {
|
||||
let defaultProps = {
|
||||
options: {
|
||||
database: 'testDatabase',
|
||||
id: 1,
|
||||
uid: 'unique-id',
|
||||
orgId: 1,
|
||||
name: 'Datasource Name',
|
||||
type: 'postgres',
|
||||
typeName: 'Postgres',
|
||||
typeLogoUrl: 'http://example.com/logo.png',
|
||||
access: 'access',
|
||||
url: 'http://example.com',
|
||||
user: 'user',
|
||||
basicAuth: true,
|
||||
basicAuthUser: 'user',
|
||||
isDefault: false,
|
||||
secureJsonFields: {},
|
||||
readOnly: false,
|
||||
withCredentials: false,
|
||||
jsonData: {
|
||||
tlsAuth: false,
|
||||
tlsAuthWithCACert: false,
|
||||
timezone: 'America/Chicago',
|
||||
tlsSkipVerify: false,
|
||||
user: 'user',
|
||||
},
|
||||
},
|
||||
};
|
||||
it('should migrate the old database field to be included in jsonData', () => {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
onOptionsChange: (options: DataSourceSettings) => {
|
||||
const jsonData = options.jsonData as SQLOptions;
|
||||
expect(options.database).toBe('');
|
||||
expect(jsonData.database).toBe('testDatabase');
|
||||
},
|
||||
};
|
||||
|
||||
// @ts-ignore Ignore this line as it's expected that
|
||||
// the database object will not be in necessary (most current) state
|
||||
const { rerender, result } = renderHook(() => useMigrateDatabaseFields(props));
|
||||
rerender();
|
||||
});
|
||||
|
||||
it('adds default max connection, max idle connection, and auto idle values when not detected', () => {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
onOptionsChange: (options: DataSourceSettings) => {
|
||||
const jsonData = options.jsonData as SQLOptions;
|
||||
expect(jsonData.maxOpenConns).toBe(SQLConnectionDefaults.MAX_CONNS);
|
||||
expect(jsonData.maxIdleConns).toBe(Math.ceil(SQLConnectionDefaults.MAX_CONNS));
|
||||
expect(jsonData.maxIdleConnsAuto).toBe(true);
|
||||
},
|
||||
};
|
||||
|
||||
// @ts-ignore Ignore this line as it's expected that
|
||||
// the database object will not be in the expected (most current) state
|
||||
const { rerender, result } = renderHook(() => useMigrateDatabaseFields(props));
|
||||
rerender();
|
||||
});
|
||||
});
|
@ -0,0 +1,63 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
|
||||
import { logDebug } from '@grafana/runtime';
|
||||
|
||||
import { SQLConnectionDefaults } from '../../constants';
|
||||
import { SQLOptions } from '../../types';
|
||||
|
||||
/**
|
||||
* 1. Moves the database field from the options object to jsonData.database and empties the database field.
|
||||
* 2. If max open connections, max idle connections, and auto idle are all undefined set these to default values.
|
||||
*/
|
||||
export function useMigrateDatabaseFields<T extends SQLOptions, S = {}>({
|
||||
onOptionsChange,
|
||||
options,
|
||||
}: DataSourcePluginOptionsEditorProps<T, S>) {
|
||||
useEffect(() => {
|
||||
const jsonData = options.jsonData;
|
||||
let newOptions = { ...options };
|
||||
let optionsUpdated = false;
|
||||
|
||||
// Migrate the database field from the column into the jsonData object
|
||||
if (options.database) {
|
||||
logDebug(`Migrating from options.database with value ${options.database} for ${options.name}`);
|
||||
newOptions.database = '';
|
||||
newOptions.jsonData = { ...jsonData, database: options.database };
|
||||
optionsUpdated = true;
|
||||
}
|
||||
|
||||
// Set default values for max open connections, max idle connection,
|
||||
// and auto idle if they're all undefined
|
||||
if (
|
||||
jsonData.maxOpenConns === undefined &&
|
||||
jsonData.maxIdleConns === undefined &&
|
||||
jsonData.maxIdleConnsAuto === undefined
|
||||
) {
|
||||
// It's expected that the default will be greater than 4
|
||||
const maxOpenConns = SQLConnectionDefaults.MAX_CONNS;
|
||||
const maxIdleConns = maxOpenConns;
|
||||
|
||||
logDebug(
|
||||
`Setting default max open connections to ${maxOpenConns} and setting max idle connection to ${maxIdleConns}`
|
||||
);
|
||||
|
||||
// Spread from the jsonData in new options in case
|
||||
// the database field was migrated as well
|
||||
newOptions.jsonData = {
|
||||
...newOptions.jsonData,
|
||||
maxOpenConns: maxOpenConns,
|
||||
maxIdleConns: maxIdleConns,
|
||||
maxIdleConnsAuto: true,
|
||||
};
|
||||
|
||||
// Make sure we issue an update if options changed
|
||||
optionsUpdated = true;
|
||||
}
|
||||
|
||||
// Only issue an update if we changed options
|
||||
if (optionsUpdated) {
|
||||
onOptionsChange(newOptions);
|
||||
}
|
||||
}, [onOptionsChange, options]);
|
||||
}
|
@ -15,3 +15,11 @@ export const MACRO_NAMES = [
|
||||
'$__unixEpochGroup',
|
||||
'$__unixEpochGroupAlias',
|
||||
];
|
||||
|
||||
/**
|
||||
* Constants for SQL connection
|
||||
* parameters and automatic settings
|
||||
*/
|
||||
export const SQLConnectionDefaults = {
|
||||
MAX_CONNS: 100,
|
||||
};
|
||||
|
@ -30,6 +30,7 @@ export interface SqlQueryForInterpolation {
|
||||
export interface SQLConnectionLimits {
|
||||
maxOpenConns: number;
|
||||
maxIdleConns: number;
|
||||
maxIdleConnsAuto: boolean;
|
||||
connMaxLifetime: number;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ import {
|
||||
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
|
||||
import { config } from 'app/core/config';
|
||||
import { ConnectionLimits } from 'app/features/plugins/sql/components/configuration/ConnectionLimits';
|
||||
import { useMigrateDatabaseField } from 'app/features/plugins/sql/components/configuration/useMigrateDatabaseField';
|
||||
import { useMigrateDatabaseFields } from 'app/features/plugins/sql/components/configuration/useMigrateDatabaseFields';
|
||||
|
||||
import { MSSQLAuthenticationType, MSSQLEncryptOptions, MssqlOptions } from '../types';
|
||||
|
||||
@ -35,7 +35,7 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps<Ms
|
||||
const styles = useStyles2(getStyles);
|
||||
const jsonData = options.jsonData;
|
||||
|
||||
useMigrateDatabaseField(props);
|
||||
useMigrateDatabaseFields(props);
|
||||
|
||||
const onResetPassword = () => {
|
||||
updateDatasourcePluginResetOption(props, 'password');
|
||||
@ -232,13 +232,7 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps<Ms
|
||||
) : null}
|
||||
</FieldSet>
|
||||
|
||||
<ConnectionLimits
|
||||
labelWidth={shortWidth}
|
||||
jsonData={jsonData}
|
||||
onPropertyChanged={(property, value) => {
|
||||
updateDatasourcePluginJsonDataOption(props, property, value);
|
||||
}}
|
||||
></ConnectionLimits>
|
||||
<ConnectionLimits labelWidth={shortWidth} options={options} onOptionsChange={onOptionsChange} />
|
||||
|
||||
<FieldSet label="MS SQL details">
|
||||
<InlineField
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
import { config } from 'app/core/config';
|
||||
import { ConnectionLimits } from 'app/features/plugins/sql/components/configuration/ConnectionLimits';
|
||||
import { TLSSecretsConfig } from 'app/features/plugins/sql/components/configuration/TLSSecretsConfig';
|
||||
import { useMigrateDatabaseField } from 'app/features/plugins/sql/components/configuration/useMigrateDatabaseField';
|
||||
import { useMigrateDatabaseFields } from 'app/features/plugins/sql/components/configuration/useMigrateDatabaseFields';
|
||||
|
||||
import { MySQLOptions } from '../types';
|
||||
|
||||
@ -29,7 +29,7 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps<My
|
||||
const { options, onOptionsChange } = props;
|
||||
const jsonData = options.jsonData;
|
||||
|
||||
useMigrateDatabaseField(props);
|
||||
useMigrateDatabaseFields(props);
|
||||
|
||||
const onResetPassword = () => {
|
||||
updateDatasourcePluginResetOption(props, 'password');
|
||||
@ -166,13 +166,7 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps<My
|
||||
</FieldSet>
|
||||
) : null}
|
||||
|
||||
<ConnectionLimits
|
||||
labelWidth={WIDTH_SHORT}
|
||||
jsonData={jsonData}
|
||||
onPropertyChanged={(property, value) => {
|
||||
updateDatasourcePluginJsonDataOption(props, property, value);
|
||||
}}
|
||||
></ConnectionLimits>
|
||||
<ConnectionLimits labelWidth={WIDTH_SHORT} options={options} onOptionsChange={onOptionsChange} />
|
||||
|
||||
<FieldSet label="MySQL details">
|
||||
<InlineField
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
import { config } from 'app/core/config';
|
||||
import { ConnectionLimits } from 'app/features/plugins/sql/components/configuration/ConnectionLimits';
|
||||
import { TLSSecretsConfig } from 'app/features/plugins/sql/components/configuration/TLSSecretsConfig';
|
||||
import { useMigrateDatabaseField } from 'app/features/plugins/sql/components/configuration/useMigrateDatabaseField';
|
||||
import { useMigrateDatabaseFields } from 'app/features/plugins/sql/components/configuration/useMigrateDatabaseFields';
|
||||
|
||||
import { PostgresOptions, PostgresTLSMethods, PostgresTLSModes, SecureJsonData } from '../types';
|
||||
|
||||
@ -49,7 +49,7 @@ export const PostgresConfigEditor = (props: DataSourcePluginOptionsEditorProps<P
|
||||
|
||||
useAutoDetectFeatures({ props, setVersionOptions });
|
||||
|
||||
useMigrateDatabaseField(props);
|
||||
useMigrateDatabaseFields(props);
|
||||
|
||||
const { options, onOptionsChange } = props;
|
||||
const jsonData = options.jsonData;
|
||||
@ -246,13 +246,7 @@ export const PostgresConfigEditor = (props: DataSourcePluginOptionsEditorProps<P
|
||||
</FieldSet>
|
||||
) : null}
|
||||
|
||||
<ConnectionLimits
|
||||
labelWidth={labelWidthShort}
|
||||
jsonData={jsonData}
|
||||
onPropertyChanged={(property, value) => {
|
||||
updateDatasourcePluginJsonDataOption(props, property, value);
|
||||
}}
|
||||
></ConnectionLimits>
|
||||
<ConnectionLimits labelWidth={labelWidthShort} options={options} onOptionsChange={onOptionsChange} />
|
||||
|
||||
<FieldSet label="PostgreSQL details">
|
||||
<InlineField
|
||||
|
Loading…
Reference in New Issue
Block a user