Skip to content

Commit

Permalink
Allow customizing ES client maxSockets (#126937)
Browse files Browse the repository at this point in the history
* Allow customizing ES client maxSockets

* Make maxSockets required (schema defaults to Infinity)

* Fix UTs

* Misc tweaks + extra UTs

* Update asciidoc

* Code cleanup

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
gsoldevila and kibanamachine authored Mar 16, 2022
1 parent 76f491b commit bbddc42
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 3 deletions.
4 changes: 4 additions & 0 deletions config/kibana.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
# must be a positive integer.
#elasticsearch.requestTimeout: 30000

# The maximum number of sockets that can be used for communications with elasticsearch.
# Defaults to `Infinity`.
#elasticsearch.maxSockets: 1024

# Specifies whether Kibana should use compression for communications with elasticsearch
# Defaults to `false`.
#elasticsearch.compression: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Configuration options to be used to create a [cluster client](./kibana-plugin-co
<b>Signature:</b>

```typescript
export declare type ElasticsearchClientConfig = Pick<ElasticsearchConfig, 'customHeaders' | 'compression' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'requestHeadersWhitelist' | 'sniffInterval' | 'hosts' | 'username' | 'password' | 'serviceAccountToken'> & {
export declare type ElasticsearchClientConfig = Pick<ElasticsearchConfig, 'customHeaders' | 'maxSockets' | 'compression' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'requestHeadersWhitelist' | 'sniffInterval' | 'hosts' | 'username' | 'password' | 'serviceAccountToken'> & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ClientOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ClientOptions['requestTimeout'];
ssl?: Partial<ElasticsearchConfig['ssl']>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [ElasticsearchConfig](./kibana-plugin-core-server.elasticsearchconfig.md) &gt; [maxSockets](./kibana-plugin-core-server.elasticsearchconfig.maxsockets.md)

## ElasticsearchConfig.maxSockets property

The maximum number of sockets that can be used for communications with elasticsearch.

<b>Signature:</b>

```typescript
readonly maxSockets: number;
```
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export declare class ElasticsearchConfig
| [healthCheckDelay](./kibana-plugin-core-server.elasticsearchconfig.healthcheckdelay.md) | | Duration | The interval between health check requests Kibana sends to the Elasticsearch. |
| [hosts](./kibana-plugin-core-server.elasticsearchconfig.hosts.md) | | string\[\] | Hosts that the client will connect to. If sniffing is enabled, this list will be used as seeds to discover the rest of your cluster. |
| [ignoreVersionMismatch](./kibana-plugin-core-server.elasticsearchconfig.ignoreversionmismatch.md) | | boolean | Whether to allow kibana to connect to a non-compatible elasticsearch node. |
| [maxSockets](./kibana-plugin-core-server.elasticsearchconfig.maxsockets.md) | | number | The maximum number of sockets that can be used for communications with elasticsearch. |
| [password?](./kibana-plugin-core-server.elasticsearchconfig.password.md) | | string | <i>(Optional)</i> If Elasticsearch is protected with basic authentication, this setting provides the password that the Kibana server uses to perform its administrative functions. |
| [pingTimeout](./kibana-plugin-core-server.elasticsearchconfig.pingtimeout.md) | | Duration | Timeout after which PING HTTP request will be aborted and retried. |
| [requestHeadersWhitelist](./kibana-plugin-core-server.elasticsearchconfig.requestheaderswhitelist.md) | | string\[\] | List of Kibana client-side headers to send to Elasticsearch when request scoped cluster client is used. If this is an empty array then \*no\* client-side will be sent. |
Expand Down
4 changes: 4 additions & 0 deletions docs/setup/settings.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ enforce even rudimentary CSP rules, though {kib} is still accessible. This
configuration is effectively ignored when <<csp-strict, `csp.strict`>> is enabled.
*Default: `true`*

|[[elasticsearch-maxSockets]] `elasticsearch.maxSockets`
| The maximum number of sockets that can be used for communications with elasticsearch.
*Default: `Infinity`*

| `elasticsearch.customHeaders:`
| Header names and values to send to {es}. Any custom headers cannot be
overwritten by client-side headers, regardless of the
Expand Down
13 changes: 13 additions & 0 deletions src/core/server/elasticsearch/client/client_config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const createConfig = (
return {
customHeaders: {},
compression: false,
maxSockets: Infinity,
sniffOnStart: false,
sniffOnConnectionFault: false,
sniffInterval: false,
Expand Down Expand Up @@ -107,6 +108,18 @@ describe('parseClientOptions', () => {
});
});

describe('`maxSockets` option', () => {
it('uses the specified config value', () => {
const options = parseClientOptions(createConfig({ maxSockets: 1024 }), false);
expect(options.agent).toHaveProperty('maxSockets', 1024);
});

it('defaults to `Infinity` if not specified by the config', () => {
const options = parseClientOptions(createConfig({}), false);
expect(options.agent).toHaveProperty('maxSockets', Infinity);
});
});

describe('`compression` option', () => {
it('`compression` is true', () => {
const options = parseClientOptions(createConfig({ compression: true }), false);
Expand Down
3 changes: 2 additions & 1 deletion src/core/server/elasticsearch/client/client_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { DEFAULT_HEADERS } from '../default_headers';
export type ElasticsearchClientConfig = Pick<
ElasticsearchConfig,
| 'customHeaders'
| 'maxSockets'
| 'compression'
| 'sniffOnStart'
| 'sniffOnConnectionFault'
Expand Down Expand Up @@ -61,7 +62,7 @@ export function parseClientOptions(
// fixes https://github.com/elastic/kibana/issues/101944
disablePrototypePoisoningProtection: true,
agent: {
maxSockets: Infinity,
maxSockets: config.maxSockets,
keepAlive: config.keepAlive ?? true,
},
compression: config.compression,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const createConfig = (
sniffOnStart: false,
sniffOnConnectionFault: false,
sniffInterval: false,
maxSockets: Infinity,
compression: false,
requestHeadersWhitelist: ['authorization'],
customHeaders: {},
Expand Down
40 changes: 40 additions & 0 deletions src/core/server/elasticsearch/elasticsearch_config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ test('set correct defaults', () => {
"http://localhost:9200",
],
"ignoreVersionMismatch": false,
"maxSockets": Infinity,
"password": undefined,
"pingTimeout": "PT30S",
"requestHeadersWhitelist": Array [
Expand Down Expand Up @@ -80,6 +81,45 @@ test('#hosts accepts both string and array of strings', () => {
expect(configValue.hosts).toEqual(['http://some.host:1234', 'https://some.another.host']);
});

describe('#maxSockets', () => {
test('accepts positive numeric values', () => {
const configValue = new ElasticsearchConfig(config.schema.validate({ maxSockets: 512 }));
expect(configValue.maxSockets).toEqual(512);
});

test('throws if it does not contain a numeric value', () => {
expect(() => {
config.schema.validate({ maxSockets: 'foo' });
}).toThrowErrorMatchingInlineSnapshot(
`"[maxSockets]: expected value of type [number] but got [string]"`
);

expect(() => {
config.schema.validate({ maxSockets: true });
}).toThrowErrorMatchingInlineSnapshot(
`"[maxSockets]: expected value of type [number] but got [boolean]"`
);
});

test('throws if it does not contain a valid numeric value', () => {
expect(() => {
config.schema.validate({ maxSockets: -1 });
}).toThrowErrorMatchingInlineSnapshot(
'"[maxSockets]: Value must be equal to or greater than [1]."'
);

expect(() => {
config.schema.validate({ maxSockets: 0 });
}).toThrowErrorMatchingInlineSnapshot(
'"[maxSockets]: Value must be equal to or greater than [1]."'
);

expect(() => {
config.schema.validate({ maxSockets: Infinity });
}).toThrowErrorMatchingInlineSnapshot('"[maxSockets]: \\"maxSockets\\" cannot be infinity"');
});
});

test('#requestHeadersWhitelist accepts both string and array of strings', () => {
let configValue = new ElasticsearchConfig(
config.schema.validate({ requestHeadersWhitelist: 'token' })
Expand Down
7 changes: 7 additions & 0 deletions src/core/server/elasticsearch/elasticsearch_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const configSchema = schema.object({
hosts: schema.oneOf([hostURISchema, schema.arrayOf(hostURISchema, { minSize: 1 })], {
defaultValue: 'http://localhost:9200',
}),
maxSockets: schema.number({ defaultValue: Infinity, min: 1 }),
compression: schema.boolean({ defaultValue: false }),
username: schema.maybe(
schema.string({
Expand Down Expand Up @@ -298,6 +299,11 @@ export class ElasticsearchConfig {
*/
public readonly apiVersion: string;

/**
* The maximum number of sockets that can be used for communications with elasticsearch.
*/
public readonly maxSockets: number;

/**
* Whether to use compression for communications with elasticsearch.
*/
Expand Down Expand Up @@ -405,6 +411,7 @@ export class ElasticsearchConfig {
this.password = rawConfig.password;
this.serviceAccountToken = rawConfig.serviceAccountToken;
this.customHeaders = rawConfig.customHeaders;
this.maxSockets = rawConfig.maxSockets;
this.compression = rawConfig.compression;
this.skipStartupConnectionCheck = rawConfig.skipStartupConnectionCheck;

Expand Down
4 changes: 3 additions & 1 deletion src/core/server/server.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ export const config: {
sniffInterval: Type<false | Duration>;
sniffOnConnectionFault: Type<boolean>;
hosts: Type<string | string[]>;
maxSockets: Type<number>;
compression: Type<boolean>;
username: Type<string | undefined>;
password: Type<string | undefined>;
Expand Down Expand Up @@ -889,7 +890,7 @@ export { EcsEventType }
export type ElasticsearchClient = Omit<Client, 'connectionPool' | 'serializer' | 'extend' | 'close' | 'diagnostic'>;

// @public
export type ElasticsearchClientConfig = Pick<ElasticsearchConfig, 'customHeaders' | 'compression' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'requestHeadersWhitelist' | 'sniffInterval' | 'hosts' | 'username' | 'password' | 'serviceAccountToken'> & {
export type ElasticsearchClientConfig = Pick<ElasticsearchConfig, 'customHeaders' | 'maxSockets' | 'compression' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'requestHeadersWhitelist' | 'sniffInterval' | 'hosts' | 'username' | 'password' | 'serviceAccountToken'> & {
pingTimeout?: ElasticsearchConfig['pingTimeout'] | ClientOptions['pingTimeout'];
requestTimeout?: ElasticsearchConfig['requestTimeout'] | ClientOptions['requestTimeout'];
ssl?: Partial<ElasticsearchConfig['ssl']>;
Expand All @@ -907,6 +908,7 @@ export class ElasticsearchConfig {
readonly healthCheckDelay: Duration;
readonly hosts: string[];
readonly ignoreVersionMismatch: boolean;
readonly maxSockets: number;
readonly password?: string;
readonly pingTimeout: Duration;
readonly requestHeadersWhitelist: string[];
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/monitoring/server/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ describe('config schema', () => {
"ignoreVersionMismatch": false,
"logFetchCount": 10,
"logQueries": false,
"maxSockets": Infinity,
"pingTimeout": "PT30S",
"requestHeadersWhitelist": Array [
"authorization",
Expand Down

0 comments on commit bbddc42

Please sign in to comment.