Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Refactor ElasticSearchBackend to make it testable
Browse files Browse the repository at this point in the history
  • Loading branch information
maciekop-l2b committed Apr 24, 2024
1 parent 9e7e9c8 commit 80f1a6e
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 111 deletions.
98 changes: 98 additions & 0 deletions packages/backend-tools/src/elastic-search/ElasticSearchBackend.ts
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 packages/backend-tools/src/elastic-search/ElasticSearchClient.ts
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,
})
}
}
2 changes: 1 addition & 1 deletion packages/backend-tools/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from './elastic-search/ElasticSearchBackend'
export * from './env'
export * from './logger/ElasticSearchBackend'
export * from './logger/interfaces'
export * from './logger/LogFormatterEcs'
export * from './logger/LogFormatterJson'
Expand Down
110 changes: 0 additions & 110 deletions packages/backend-tools/src/logger/ElasticSearchBackend.ts

This file was deleted.

0 comments on commit 80f1a6e

Please sign in to comment.