This repository has been archived by the owner on Apr 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor ElasticSearchBackend to make it testable
- Loading branch information
1 parent
9e7e9c8
commit 80f1a6e
Showing
4 changed files
with
139 additions
and
111 deletions.
There are no files selected for viewing
98 changes: 98 additions & 0 deletions
98
packages/backend-tools/src/elastic-search/ElasticSearchBackend.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import { v4 as uuidv4 } from 'uuid' | ||
|
||
import { LoggerBackend } from '../logger/interfaces' | ||
import { | ||
ElasticSearchClient, | ||
ElasticSearchClientOptions, | ||
} from './ElasticSearchClient' | ||
|
||
export interface ElasticSearchBackendOptions | ||
extends ElasticSearchClientOptions { | ||
flushInterval?: number | ||
indexPrefix?: string | ||
} | ||
|
||
export type UuidProvider = () => string | ||
|
||
export class ElasticSearchBackend implements LoggerBackend { | ||
private readonly buffer: string[] | ||
|
||
constructor( | ||
private readonly options: ElasticSearchBackendOptions, | ||
private readonly client: ElasticSearchClient = new ElasticSearchClient( | ||
options, | ||
), | ||
private readonly uuidProvider: UuidProvider = uuidv4, | ||
) { | ||
this.buffer = [] | ||
this.start() | ||
} | ||
|
||
public debug(message: string): void { | ||
this.buffer.push(message) | ||
} | ||
|
||
public log(message: string): void { | ||
this.buffer.push(message) | ||
} | ||
|
||
public warn(message: string): void { | ||
this.buffer.push(message) | ||
} | ||
|
||
public error(message: string): void { | ||
this.buffer.push(message) | ||
} | ||
|
||
private start(): void { | ||
// eslint-disable-next-line @typescript-eslint/no-misused-promises | ||
setInterval(async () => { | ||
await this.flushLogs() | ||
}, this.options.flushInterval ?? 10000) | ||
} | ||
|
||
private async flushLogs(): Promise<void> { | ||
if (!this.buffer.length) { | ||
return | ||
} | ||
|
||
try { | ||
const index = await this.createIndex() | ||
|
||
// copy buffer contents as it may change during async operations below | ||
const batch = [...this.buffer] | ||
|
||
//clear buffer | ||
this.buffer.splice(0) | ||
|
||
const documents = batch.map( | ||
(log) => | ||
({ | ||
id: this.uuidProvider(), | ||
...JSON.parse(log), | ||
} as object), | ||
) | ||
|
||
const success = await this.client.bulk(documents, index) | ||
|
||
if (!success) { | ||
throw new Error('Failed to push liogs to Elastic Search node') | ||
} | ||
} catch (error) { | ||
console.log(error) | ||
} | ||
} | ||
|
||
private async createIndex(): Promise<string> { | ||
const now = new Date() | ||
const indexName = `${ | ||
this.options.indexPrefix ?? 'logs-' | ||
}-${now.getFullYear()}.${now.getMonth()}.${now.getDay()}` | ||
|
||
const exist = await this.client.indexExist(indexName) | ||
if (!exist) { | ||
await this.client.indexCreate(indexName) | ||
} | ||
return indexName | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
packages/backend-tools/src/elastic-search/ElasticSearchClient.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { Client } from '@elastic/elasticsearch' | ||
|
||
export interface ElasticSearchClientOptions { | ||
node: string | ||
apiKey: string | ||
} | ||
|
||
// hides complexity of ElastiSearch client API | ||
export class ElasticSearchClient { | ||
private readonly client: Client | ||
|
||
constructor(private readonly options: ElasticSearchClientOptions) { | ||
this.client = new Client({ | ||
node: options.node, | ||
auth: { | ||
apiKey: options.apiKey, | ||
}, | ||
}) | ||
} | ||
|
||
public async bulk(documents: object[], index: string): Promise<boolean> { | ||
const operations = documents.flatMap((doc: object) => [ | ||
{ index: { _index: index } }, | ||
doc, | ||
]) | ||
|
||
const bulkResponse = await this.client.bulk({ refresh: true, operations }) | ||
return bulkResponse.errors | ||
} | ||
|
||
public async indexExist(index: string): Promise<boolean> { | ||
return await this.client.indices.exists({ index }) | ||
} | ||
|
||
public async indexCreate(index: string): Promise<void> { | ||
await this.client.indices.create({ | ||
index, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 0 additions & 110 deletions
110
packages/backend-tools/src/logger/ElasticSearchBackend.ts
This file was deleted.
Oops, something went wrong.