winston-openobserve
Version:
Winston OpenObserve transport
120 lines (101 loc) • 2.63 kB
text/typescript
import Transport from 'winston-transport';
import { OpenObserveTransportOptions } from './interface';
import { Sender } from './sender';
import { MESSAGE } from 'triple-beam';
import * as assert from 'assert';
import exitHook from 'async-exit-hook';
function isURL(url: string) {
try {
new URL('', url);
return true;
} catch (error) {
return false;
}
}
export class OpenObserveTransport extends Transport {
#sender: Sender;
#options: OpenObserveTransportOptions;
public constructor(options: OpenObserveTransportOptions) {
super();
assert.ok(options.defaultOrg, 'Set default org_id');
assert.ok(options.defaultStream, 'Set default stream name');
assert.ok(isURL(options.host), 'Host URL can not parse');
this.#options = {
bulk: true,
gracefulShutdown: true,
timeout: 10000,
interval: 10000,
cleanOnRequestError: false,
useNow: false,
...options,
};
this.#sender = new Sender(this.#options);
if (this.#options.gracefulShutdown) {
exitHook(() => {
this.close();
});
}
}
#getTimestamp(timestamp) {
if (this.#options.useNow) return Date.now();
let ts;
if (timestamp) {
ts = new Date(timestamp).getTime();
ts = isNaN(ts) ? Date.now() : ts;
} else {
ts = Date.now();
}
return ts;
}
public override log(info: any, next: () => void) {
setImmediate(() => {
this.emit('logged', info);
});
let {
label,
labels,
timestamp,
level,
message,
org,
stream,
bulk,
...rest
} = info;
timestamp = this.#getTimestamp(timestamp);
let openObserveLabels: Record<string, any> = {
level,
};
labels = Object.assign({}, this.#options.labels);
for (const key in openObserveLabels) {
if (Object.prototype.hasOwnProperty.call(openObserveLabels, key)) {
const value = openObserveLabels[key];
if (typeof value !== 'string') {
openObserveLabels[key] = String(value);
}
}
}
message = !!this.#options.format
? info[MESSAGE]
: `${message} ${
rest && Object.keys(rest).length > 0 ? JSON.stringify(rest) : ''
}`;
this.#sender
.push(
{
labels,
timestamp,
level,
message,
label,
orgId: org ?? this.#options.defaultOrg,
streamName: stream ?? this.#options.defaultStream,
},
bulk ?? this.#options.bulk,
)
.then(next);
}
public override close(): void {
this.#sender.close();
}
}