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>
MattiasSegerdahl-update-contribute.md
Kyle Cunningham 2 years ago committed by GitHub
parent 43def489f4
commit 1fbac96bd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      packages/grafana-data/src/types/config.ts
  2. 5
      packages/grafana-runtime/src/config.ts
  3. 8
      pkg/api/dtos/frontend_settings.go
  4. 6
      pkg/api/frontendsettings.go
  5. 12
      public/app/features/plugins/sql/components/configuration/ConnectionLimits.tsx
  6. 19
      public/app/features/plugins/sql/components/configuration/useMigrateDatabaseFields.test.ts
  7. 22
      public/app/features/plugins/sql/components/configuration/useMigrateDatabaseFields.ts
  8. 8
      public/app/features/plugins/sql/constants.ts

@ -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>
} }
> >

@ -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);
}, },
}; };

@ -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,
};

Loading…
Cancel
Save