Postgres: Switch the datasource plugin from lib/pq to pgx (#103961)

* Create libpqToPGX feature toggle

* Refactor PostgreSQL datasource to support PGX with feature toggle

- Updated `ProvideService` to accept feature toggles for enabling PGX.
- Modified integration tests to use the new PGX connection method.
- Introduced new functions for handling PGX connections and queries.
- Enhanced TLS configuration handling for PostgreSQL connections.
- Updated existing tests to ensure compatibility with PGX and new connection methods.

* Update PostgreSQL datasource to enhance connection pooling and error handling

- Increased `MaxOpenConns` to 10 in integration tests for improved connection management.
- Refactored connection handling in `newPostgresPGX` to return a connection pool instead of a single connection.
- Updated health check error handling to utilize context and feature toggles for better error reporting.
- Adjusted `DisposePGX` method to close the connection pool properly.
- Enhanced query execution to acquire connections from the pool, ensuring efficient resource usage.

* Cleanup

* Revert postgres_test unnecessary changes

* Rename feature toggle from `libpqToPGX` to `postgresDSUsePGX`

* Add null check to dispose method

* Fix lint issues

* Refactor connection string generation

* Address comment in health check file

* Rename p to pool

* Refactor executeQueryPGX and split into multiple functions

* Fix lint issues

* The returning error message from PGX is enough no need to separate the error code.

* Move TLS handling to newPostgresPGX function

* Disable ssl for integration tests

* Use MaxIdleConns option

* Remove old feature toggle

* Rename`generateConnectionConfigPGX` to `generateConnectionStringPGX`

* Add back part of the error messages

* Don't show max idle connections option when PGX enabled

* Address comments from Sriram

* Add back Sriram's changes

* PostgreSQL: Rework tls manager to use temporary files instead (#105330)

* Rework tls manager to use temporary files instead

* Lint and test fixes

* Update pkg/tsdb/grafana-postgresql-datasource/postgres.go

Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com>

* Update betterer

---------

Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com>

---------

Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com>
This commit is contained in:
Zoltán Bedi
2025-05-26 08:54:18 +02:00
committed by GitHub
co-authored by Ivana Huckova
parent 745eda2848
commit 1e383b0c1e
25 changed files with 1233 additions and 778 deletions
@@ -5,6 +5,8 @@ import { Field, Icon, InlineLabel, Label, Stack, Switch, Tooltip } from '@grafan
import { SQLConnectionLimits, SQLOptions } from '../../types';
import { MaxLifetimeField } from './MaxLifetimeField';
import { MaxOpenConnectionsField } from './MaxOpenConnectionsField';
import { NumberInput } from './NumberInput';
interface Props<T> {
@@ -84,36 +86,11 @@ export const ConnectionLimits = <T extends SQLConnectionLimits>(props: Props<T>)
return (
<ConfigSubSection title="Connection limits">
<Field
label={
<Label>
<Stack gap={0.5}>
<span>Max open</span>
<Tooltip
content={
<span>
The maximum number of open connections to the database. If <i>Max idle connections</i> is greater
than 0 and the <i>Max open connections</i> is less than <i>Max idle connections</i>, then
<i>Max idle connections</i> will be reduced to match the <i>Max open connections</i> limit. If set
to 0, there is no limit on the number of open connections.
</span>
}
>
<Icon name="info-circle" size="sm" />
</Tooltip>
</Stack>
</Label>
}
>
<NumberInput
value={jsonData.maxOpenConns}
defaultValue={config.sqlConnectionLimits.maxOpenConns}
onChange={(value) => {
onMaxConnectionsChanged(value);
}}
width={labelWidth}
/>
</Field>
<MaxOpenConnectionsField
labelWidth={labelWidth}
onMaxConnectionsChanged={onMaxConnectionsChanged}
jsonData={jsonData}
/>
<Field
label={
@@ -173,34 +150,11 @@ export const ConnectionLimits = <T extends SQLConnectionLimits>(props: Props<T>)
)}
</Field>
<Field
label={
<Label>
<Stack gap={0.5}>
<span>Max lifetime</span>
<Tooltip
content={
<span>
The maximum amount of time in seconds a connection may be reused. If set to 0, connections are
reused forever.
</span>
}
>
<Icon name="info-circle" size="sm" />
</Tooltip>
</Stack>
</Label>
}
>
<NumberInput
value={jsonData.connMaxLifetime}
defaultValue={config.sqlConnectionLimits.connMaxLifetime}
onChange={(value) => {
onJSONDataNumberChanged('connMaxLifetime')(value);
}}
width={labelWidth}
/>
</Field>
<MaxLifetimeField
labelWidth={labelWidth}
onMaxLifetimeChanged={onJSONDataNumberChanged('connMaxLifetime')}
jsonData={jsonData}
/>
</ConfigSubSection>
);
};
@@ -0,0 +1,42 @@
import { config } from '@grafana/runtime';
import { Field, Icon, Label, Stack, Tooltip } from '@grafana/ui';
import { SQLOptions } from '../../types';
import { NumberInput } from './NumberInput';
interface Props {
labelWidth: number;
onMaxLifetimeChanged: (number?: number) => void;
jsonData: SQLOptions;
}
export function MaxLifetimeField({ labelWidth, onMaxLifetimeChanged, jsonData }: Props) {
return (
<Field
label={
<Label>
<Stack gap={0.5}>
<span>Max lifetime</span>
<Tooltip
content={
<span>
The maximum amount of time in seconds a connection may be reused. If set to 0, connections are reused
forever.
</span>
}
>
<Icon name="info-circle" size="sm" />
</Tooltip>
</Stack>
</Label>
}
>
<NumberInput
value={jsonData.connMaxLifetime}
defaultValue={config.sqlConnectionLimits.connMaxLifetime}
onChange={onMaxLifetimeChanged}
width={labelWidth}
/>
</Field>
);
}
@@ -0,0 +1,45 @@
import { config } from '@grafana/runtime';
import { Field, Icon, Label, Stack, Tooltip } from '@grafana/ui';
import { SQLOptions } from '../../types';
import { NumberInput } from './NumberInput';
interface Props {
labelWidth: number;
onMaxConnectionsChanged: (number?: number) => void;
jsonData: SQLOptions;
}
export function MaxOpenConnectionsField({ labelWidth, onMaxConnectionsChanged, jsonData }: Props) {
return (
<Field
label={
<Label>
<Stack gap={0.5}>
<span>Max open</span>
<Tooltip
content={
<span>
The maximum number of open connections to the database. If <i>Max idle connections</i> is greater than
0 and the <i>Max open connections</i> is less than <i>Max idle connections</i>, then
<i>Max idle connections</i> will be reduced to match the <i>Max open connections</i> limit. If set to
0, there is no limit on the number of open connections.
</span>
}
>
<Icon name="info-circle" size="sm" />
</Tooltip>
</Stack>
</Label>
}
>
<NumberInput
value={jsonData.maxOpenConns}
defaultValue={config.sqlConnectionLimits.maxOpenConns}
onChange={onMaxConnectionsChanged}
width={labelWidth}
/>
</Field>
);
}