mirror of
https://github.com/grafana/grafana.git
synced 2026-09-05 04:40:13 -05:00
SQL Datasources: Update behavior of default connection limits (#66687)
* Update behavior of defaults in connection limits * Refactor to use config object instead * Refactor remove unneeded function --------- Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>
This commit is contained in:
co-authored by
Zoltán Bedi
parent
43def489f4
commit
1fbac96bd4
@@ -228,6 +228,13 @@ export interface GrafanaConfig {
|
|||||||
rudderstackDataPlaneUrl: string | undefined;
|
rudderstackDataPlaneUrl: string | undefined;
|
||||||
rudderstackSdkUrl: string | undefined;
|
rudderstackSdkUrl: string | undefined;
|
||||||
rudderstackConfigUrl: string | undefined;
|
rudderstackConfigUrl: string | undefined;
|
||||||
|
sqlConnectionLimits: SqlConnectionLimits;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SqlConnectionLimits {
|
||||||
|
maxOpenConns: number;
|
||||||
|
maxIdleConns: number;
|
||||||
|
connMaxLifetime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AuthSettings {
|
export interface AuthSettings {
|
||||||
|
|||||||
@@ -154,6 +154,11 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
|||||||
rudderstackDataPlaneUrl: undefined;
|
rudderstackDataPlaneUrl: undefined;
|
||||||
rudderstackSdkUrl: undefined;
|
rudderstackSdkUrl: undefined;
|
||||||
rudderstackConfigUrl: undefined;
|
rudderstackConfigUrl: undefined;
|
||||||
|
sqlConnectionLimits = {
|
||||||
|
maxOpenConns: 100,
|
||||||
|
maxIdleConns: 100,
|
||||||
|
connMaxLifetime: 14400,
|
||||||
|
};
|
||||||
|
|
||||||
tokenExpirationDayLimit: undefined;
|
tokenExpirationDayLimit: undefined;
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,12 @@ type FrontendSettingsWhitelabelingDTO struct {
|
|||||||
PublicDashboardFooter *FrontendSettingsPublicDashboardFooterConfigDTO `json:"publicDashboardFooter,omitempty"` // PR TODO: type this properly
|
PublicDashboardFooter *FrontendSettingsPublicDashboardFooterConfigDTO `json:"publicDashboardFooter,omitempty"` // PR TODO: type this properly
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FrontendSettingsSqlConnectionLimitsDTO struct {
|
||||||
|
MaxOpenConns int `json:"maxOpenConns"`
|
||||||
|
MaxIdleConns int `json:"maxIdleConns"`
|
||||||
|
ConnMaxLifetime int `json:"connMaxLifetime"`
|
||||||
|
}
|
||||||
|
|
||||||
type FrontendSettingsDTO struct {
|
type FrontendSettingsDTO struct {
|
||||||
DefaultDatasource string `json:"defaultDatasource"`
|
DefaultDatasource string `json:"defaultDatasource"`
|
||||||
Datasources map[string]plugins.DataSourceDTO `json:"datasources"`
|
Datasources map[string]plugins.DataSourceDTO `json:"datasources"`
|
||||||
@@ -215,6 +221,8 @@ type FrontendSettingsDTO struct {
|
|||||||
|
|
||||||
PluginsCDNBaseURL string `json:"pluginsCDNBaseURL,omitempty"`
|
PluginsCDNBaseURL string `json:"pluginsCDNBaseURL,omitempty"`
|
||||||
|
|
||||||
|
SqlConnectionLimits FrontendSettingsSqlConnectionLimitsDTO `json:"sqlConnectionLimits"`
|
||||||
|
|
||||||
// Enterprise
|
// Enterprise
|
||||||
Licensing *FrontendSettingsLicensingDTO `json:"licensing,omitempty"`
|
Licensing *FrontendSettingsLicensingDTO `json:"licensing,omitempty"`
|
||||||
Whitelabeling *FrontendSettingsWhitelabelingDTO `json:"whitelabeling,omitempty"`
|
Whitelabeling *FrontendSettingsWhitelabelingDTO `json:"whitelabeling,omitempty"`
|
||||||
|
|||||||
@@ -220,6 +220,12 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
|
|||||||
TokenExpirationDayLimit: hs.Cfg.SATokenExpirationDayLimit,
|
TokenExpirationDayLimit: hs.Cfg.SATokenExpirationDayLimit,
|
||||||
|
|
||||||
SnapshotEnabled: hs.Cfg.SnapshotEnabled,
|
SnapshotEnabled: hs.Cfg.SnapshotEnabled,
|
||||||
|
|
||||||
|
SqlConnectionLimits: dtos.FrontendSettingsSqlConnectionLimitsDTO{
|
||||||
|
MaxOpenConns: hs.Cfg.SqlDatasourceMaxOpenConnsDefault,
|
||||||
|
MaxIdleConns: hs.Cfg.SqlDatasourceMaxIdleConnsDefault,
|
||||||
|
ConnMaxLifetime: hs.Cfg.SqlDatasourceMaxConnLifetimeDefault,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if hs.Cfg.UnifiedAlerting.StateHistory.Enabled {
|
if hs.Cfg.UnifiedAlerting.StateHistory.Enabled {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { DataSourceSettings } from '@grafana/data';
|
import { DataSourceSettings } from '@grafana/data';
|
||||||
|
import { config } from '@grafana/runtime';
|
||||||
import { FieldSet, InlineField, InlineFieldRow, InlineSwitch } from '@grafana/ui';
|
import { FieldSet, InlineField, InlineFieldRow, InlineSwitch } from '@grafana/ui';
|
||||||
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
|
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
|
||||||
|
|
||||||
import { SQLConnectionDefaults } from '../../constants';
|
|
||||||
import { SQLConnectionLimits, SQLOptions } from '../../types';
|
import { SQLConnectionLimits, SQLOptions } from '../../types';
|
||||||
|
|
||||||
interface Props<T> {
|
interface Props<T> {
|
||||||
@@ -47,7 +47,7 @@ export const ConnectionLimits = <T extends SQLConnectionLimits>(props: Props<T>)
|
|||||||
maxOpenConns: number,
|
maxOpenConns: number,
|
||||||
maxIdleConns: number,
|
maxIdleConns: number,
|
||||||
});
|
});
|
||||||
} else if (number !== undefined) {
|
} else {
|
||||||
updateJsonData({
|
updateJsonData({
|
||||||
maxOpenConns: number,
|
maxOpenConns: number,
|
||||||
});
|
});
|
||||||
@@ -68,10 +68,10 @@ export const ConnectionLimits = <T extends SQLConnectionLimits>(props: Props<T>)
|
|||||||
if (jsonData.maxOpenConns !== undefined) {
|
if (jsonData.maxOpenConns !== undefined) {
|
||||||
maxConns = jsonData.maxOpenConns;
|
maxConns = jsonData.maxOpenConns;
|
||||||
idleConns = jsonData.maxOpenConns;
|
idleConns = jsonData.maxOpenConns;
|
||||||
} else {
|
|
||||||
maxConns = SQLConnectionDefaults.MAX_CONNS;
|
|
||||||
idleConns = SQLConnectionDefaults.MAX_CONNS;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
maxConns = jsonData.maxOpenConns;
|
||||||
|
idleConns = jsonData.maxIdleConns;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateJsonData({
|
updateJsonData({
|
||||||
@@ -124,7 +124,7 @@ export const ConnectionLimits = <T extends SQLConnectionLimits>(props: Props<T>)
|
|||||||
<span>
|
<span>
|
||||||
If enabled, automatically set the number of <i>Maximum idle connections</i> to the same value as
|
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
|
<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}).
|
default ({config.sqlConnectionLimits.maxIdleConns}).
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
+16
-3
@@ -2,11 +2,23 @@ import { renderHook } from '@testing-library/react-hooks';
|
|||||||
|
|
||||||
import { DataSourceSettings } from '@grafana/data';
|
import { DataSourceSettings } from '@grafana/data';
|
||||||
|
|
||||||
import { SQLConnectionDefaults } from '../../constants';
|
|
||||||
import { SQLOptions } from '../../types';
|
import { SQLOptions } from '../../types';
|
||||||
|
|
||||||
import { useMigrateDatabaseFields } from './useMigrateDatabaseFields';
|
import { useMigrateDatabaseFields } from './useMigrateDatabaseFields';
|
||||||
|
|
||||||
|
jest.mock('@grafana/runtime', () => {
|
||||||
|
return {
|
||||||
|
config: {
|
||||||
|
sqlConnectionLimits: {
|
||||||
|
maxOpenConns: 10,
|
||||||
|
maxIdleConns: 11,
|
||||||
|
connMaxLifetime: 12,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
logDebug: jest.fn(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
describe('Database Field Migration', () => {
|
describe('Database Field Migration', () => {
|
||||||
let defaultProps = {
|
let defaultProps = {
|
||||||
options: {
|
options: {
|
||||||
@@ -57,8 +69,9 @@ describe('Database Field Migration', () => {
|
|||||||
...defaultProps,
|
...defaultProps,
|
||||||
onOptionsChange: (options: DataSourceSettings) => {
|
onOptionsChange: (options: DataSourceSettings) => {
|
||||||
const jsonData = options.jsonData as SQLOptions;
|
const jsonData = options.jsonData as SQLOptions;
|
||||||
expect(jsonData.maxOpenConns).toBe(SQLConnectionDefaults.MAX_CONNS);
|
expect(jsonData.maxOpenConns).toBe(10);
|
||||||
expect(jsonData.maxIdleConns).toBe(Math.ceil(SQLConnectionDefaults.MAX_CONNS));
|
expect(jsonData.maxIdleConns).toBe(11);
|
||||||
|
expect(jsonData.connMaxLifetime).toBe(12);
|
||||||
expect(jsonData.maxIdleConnsAuto).toBe(true);
|
expect(jsonData.maxIdleConnsAuto).toBe(true);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
+17
-5
@@ -1,9 +1,8 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
|
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
|
||||||
import { logDebug } from '@grafana/runtime';
|
import { logDebug, config } from '@grafana/runtime';
|
||||||
|
|
||||||
import { SQLConnectionDefaults } from '../../constants';
|
|
||||||
import { SQLOptions } from '../../types';
|
import { SQLOptions } from '../../types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,9 +33,7 @@ export function useMigrateDatabaseFields<T extends SQLOptions, S = {}>({
|
|||||||
jsonData.maxIdleConns === undefined &&
|
jsonData.maxIdleConns === undefined &&
|
||||||
jsonData.maxIdleConnsAuto === undefined
|
jsonData.maxIdleConnsAuto === undefined
|
||||||
) {
|
) {
|
||||||
// It's expected that the default will be greater than 4
|
const { maxOpenConns, maxIdleConns } = config.sqlConnectionLimits;
|
||||||
const maxOpenConns = SQLConnectionDefaults.MAX_CONNS;
|
|
||||||
const maxIdleConns = maxOpenConns;
|
|
||||||
|
|
||||||
logDebug(
|
logDebug(
|
||||||
`Setting default max open connections to ${maxOpenConns} and setting max idle connection to ${maxIdleConns}`
|
`Setting default max open connections to ${maxOpenConns} and setting max idle connection to ${maxIdleConns}`
|
||||||
@@ -55,6 +52,21 @@ export function useMigrateDatabaseFields<T extends SQLOptions, S = {}>({
|
|||||||
optionsUpdated = true;
|
optionsUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the maximum connection lifetime hasn't been
|
||||||
|
// otherwise set fill in with the default from configuration
|
||||||
|
if (jsonData.connMaxLifetime === undefined) {
|
||||||
|
const { connMaxLifetime } = config.sqlConnectionLimits;
|
||||||
|
|
||||||
|
// Spread new options and add our value
|
||||||
|
newOptions.jsonData = {
|
||||||
|
...newOptions.jsonData,
|
||||||
|
connMaxLifetime: connMaxLifetime,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Note that we've updated the options
|
||||||
|
optionsUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Only issue an update if we changed options
|
// Only issue an update if we changed options
|
||||||
if (optionsUpdated) {
|
if (optionsUpdated) {
|
||||||
onOptionsChange(newOptions);
|
onOptionsChange(newOptions);
|
||||||
|
|||||||
@@ -15,11 +15,3 @@ export const MACRO_NAMES = [
|
|||||||
'$__unixEpochGroup',
|
'$__unixEpochGroup',
|
||||||
'$__unixEpochGroupAlias',
|
'$__unixEpochGroupAlias',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
|
||||||
* Constants for SQL connection
|
|
||||||
* parameters and automatic settings
|
|
||||||
*/
|
|
||||||
export const SQLConnectionDefaults = {
|
|
||||||
MAX_CONNS: 100,
|
|
||||||
};
|
|
||||||
|
|||||||
Reference in New Issue
Block a user