Add vlogs sdk for ts
This commit is contained in:
commit
430d052865
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
dist/
|
||||
build/
|
||||
node_modules/
|
31
README.md
Normal file
31
README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# vLogs SDK for JS/TS
|
||||
|
||||
A simple way to collect logs and send to the server via simple SDK.
|
||||
|
||||
- [x] Collect the logs
|
||||
- [ ] Support local retries
|
||||
|
||||
## Usages
|
||||
|
||||
```typescript
|
||||
const APP_ID = 'xxx';
|
||||
const API_KEY = 'vlogs_xxx';
|
||||
|
||||
const sdk = VLogs.create(
|
||||
VLogsOptions.builder().appId(APP_ID).apiKey(API_KEY).build()
|
||||
);
|
||||
|
||||
const request = Collector.builder()
|
||||
.message('Hello from vlogs-ts-sdk')
|
||||
.type(CollectorType.Log)
|
||||
.source(CollectorSource.Web)
|
||||
.build();
|
||||
|
||||
const response = await sdk.collect(request);
|
||||
console.log('Request: ', request);
|
||||
console.log('Response: ', response);
|
||||
```
|
||||
|
||||
### Contributors
|
||||
|
||||
- Sambo Chea <sombochea@cubetiqs.com>
|
9
jest.config.js
Normal file
9
jest.config.js
Normal file
@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
modulePathIgnorePatterns: ['<rootDir>/dist/'],
|
||||
testPathIgnorePatterns: ["/node_modules/"],
|
||||
moduleNameMapper: {
|
||||
"\\.(css|less)$": "identity-obj-proxy"
|
||||
}
|
||||
};
|
3687
package-lock.json
generated
Normal file
3687
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
42
package.json
Normal file
42
package.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "@cubetiq/vlogs",
|
||||
"version": "1.0.0",
|
||||
"description": "A simple way to collect logs and send to the server via simple SDK.",
|
||||
"main": "dist/index.js",
|
||||
"dist": {
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc -w",
|
||||
"start": "node dist/index.js",
|
||||
"test": "jest"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/CUBETIQ/vlogs_sdk_ts.git"
|
||||
},
|
||||
"keywords": [
|
||||
"vlogs"
|
||||
],
|
||||
"author": "Sambo Chea <sombochea@cubetiqs.com>",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/CUBETIQ/vlogs_sdk_ts/issues"
|
||||
},
|
||||
"homepage": "https://github.com/CUBETIQ/vlogs_sdk_ts#readme",
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.1",
|
||||
"@types/node": "^20.2.5",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"jest": "^29.5.0",
|
||||
"ts-jest": "^29.1.0",
|
||||
"typescript": "^5.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
"uuid": "^9.0.0"
|
||||
}
|
||||
}
|
2
src/index.ts
Normal file
2
src/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './model'
|
||||
export * from './vlgos'
|
692
src/model.ts
Normal file
692
src/model.ts
Normal file
@ -0,0 +1,692 @@
|
||||
import { generateUUID } from "./util";
|
||||
|
||||
enum CollectorType {
|
||||
Error,
|
||||
Event,
|
||||
Metric,
|
||||
Trace,
|
||||
Log,
|
||||
Span,
|
||||
}
|
||||
|
||||
enum CollectorSource {
|
||||
Web,
|
||||
Mobile,
|
||||
Server,
|
||||
Desktop,
|
||||
IoT,
|
||||
Other,
|
||||
}
|
||||
|
||||
enum TelegramParseMode {
|
||||
Markdown,
|
||||
MarkdownV2,
|
||||
HTML,
|
||||
}
|
||||
|
||||
|
||||
interface TelegramOptions {
|
||||
token?: string;
|
||||
chatId?: string;
|
||||
parseMode?: TelegramParseMode;
|
||||
disabled?: boolean;
|
||||
extras?: any;
|
||||
}
|
||||
|
||||
class Telegram {
|
||||
token?: string;
|
||||
chatId?: string;
|
||||
parseMode?: TelegramParseMode;
|
||||
disabled?: boolean;
|
||||
extras?: any;
|
||||
|
||||
constructor(options: TelegramOptions = {}) {
|
||||
this.token = options.token;
|
||||
this.chatId = options.chatId;
|
||||
this.parseMode = options.parseMode;
|
||||
this.disabled = options.disabled;
|
||||
this.extras = options.extras;
|
||||
}
|
||||
|
||||
toMap(): Record<string, any> {
|
||||
return {
|
||||
'token': this.token,
|
||||
'chat_id': this.chatId,
|
||||
'parse_mode': this.parseMode,
|
||||
'disabled': this.disabled,
|
||||
'extras': this.extras,
|
||||
};
|
||||
}
|
||||
|
||||
static builder(): TelegramBuilder {
|
||||
return new TelegramBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
class TelegramBuilder {
|
||||
private _token?: string;
|
||||
private _chatId?: string;
|
||||
private _parseMode?: TelegramParseMode;
|
||||
private _disabled?: boolean;
|
||||
private _extras?: any;
|
||||
|
||||
constructor() { }
|
||||
|
||||
token(token?: string): TelegramBuilder {
|
||||
this._token = token;
|
||||
return this;
|
||||
}
|
||||
|
||||
chatId(chatId?: string): TelegramBuilder {
|
||||
this._chatId = chatId;
|
||||
return this;
|
||||
}
|
||||
|
||||
parseMode(parseMode?: TelegramParseMode): TelegramBuilder {
|
||||
this._parseMode = parseMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
disabled(disabled?: boolean): TelegramBuilder {
|
||||
this._disabled = disabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
extras(extras?: any): TelegramBuilder {
|
||||
this._extras = extras;
|
||||
return this;
|
||||
}
|
||||
|
||||
build(): Telegram {
|
||||
return new Telegram({
|
||||
token: this._token,
|
||||
chatId: this._chatId,
|
||||
parseMode: this._parseMode,
|
||||
disabled: this._disabled,
|
||||
extras: this._extras,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class Discord {
|
||||
webhookId?: string;
|
||||
webhookToken?: string;
|
||||
webhookUrl?: string;
|
||||
disabled?: boolean;
|
||||
extras?: any;
|
||||
|
||||
constructor({
|
||||
webhookId,
|
||||
webhookToken,
|
||||
webhookUrl,
|
||||
disabled,
|
||||
extras,
|
||||
}: {
|
||||
webhookId?: string;
|
||||
webhookToken?: string;
|
||||
webhookUrl?: string;
|
||||
disabled?: boolean;
|
||||
extras?: any;
|
||||
}) {
|
||||
this.webhookId = webhookId;
|
||||
this.webhookToken = webhookToken;
|
||||
this.webhookUrl = webhookUrl;
|
||||
this.disabled = disabled;
|
||||
this.extras = extras;
|
||||
}
|
||||
|
||||
toMap(): Record<string, any> {
|
||||
return {
|
||||
webhook_id: this.webhookId,
|
||||
webhook_token: this.webhookToken,
|
||||
webhook_url: this.webhookUrl,
|
||||
disabled: this.disabled,
|
||||
extras: this.extras,
|
||||
};
|
||||
}
|
||||
|
||||
static builder(): DiscordBuilder {
|
||||
return new DiscordBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
class DiscordBuilder {
|
||||
private _webhookId?: string;
|
||||
private _webhookToken?: string;
|
||||
private _webhookUrl?: string;
|
||||
private _disabled?: boolean;
|
||||
private _extras?: any;
|
||||
|
||||
constructor() { }
|
||||
|
||||
webhookId(webhookId: string | undefined): DiscordBuilder {
|
||||
this._webhookId = webhookId;
|
||||
return this;
|
||||
}
|
||||
|
||||
webhookToken(webhookToken: string | undefined): DiscordBuilder {
|
||||
this._webhookToken = webhookToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
webhookUrl(webhookUrl: string | undefined): DiscordBuilder {
|
||||
this._webhookUrl = webhookUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
disabled(disabled: boolean | undefined): DiscordBuilder {
|
||||
this._disabled = disabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
extras(extras: any): DiscordBuilder {
|
||||
this._extras = extras;
|
||||
return this;
|
||||
}
|
||||
|
||||
build(): Discord {
|
||||
return new Discord({
|
||||
webhookId: this._webhookId,
|
||||
webhookToken: this._webhookToken,
|
||||
webhookUrl: this._webhookUrl,
|
||||
disabled: this._disabled,
|
||||
extras: this._extras,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class SDKInfo {
|
||||
name?: string;
|
||||
version?: string;
|
||||
versionCode?: string;
|
||||
hostname?: string;
|
||||
sender?: string;
|
||||
|
||||
constructor({
|
||||
name,
|
||||
version,
|
||||
versionCode,
|
||||
hostname,
|
||||
sender,
|
||||
}: {
|
||||
name?: string;
|
||||
version?: string;
|
||||
versionCode?: string;
|
||||
hostname?: string;
|
||||
sender?: string;
|
||||
}) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
this.versionCode = versionCode;
|
||||
this.hostname = hostname;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
toMap(): Record<string, any> {
|
||||
return {
|
||||
name: this.name,
|
||||
version: this.version,
|
||||
version_code: this.versionCode,
|
||||
hostname: this.hostname,
|
||||
sender: this.sender,
|
||||
};
|
||||
}
|
||||
|
||||
static builder(): SDKInfoBuilder {
|
||||
return new SDKInfoBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
class SDKInfoBuilder {
|
||||
private _name?: string;
|
||||
private _version?: string;
|
||||
private _versionCode?: string;
|
||||
private _hostname?: string;
|
||||
private _sender?: string;
|
||||
|
||||
constructor() { }
|
||||
|
||||
name(name: string | undefined): SDKInfoBuilder {
|
||||
this._name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
version(version: string | undefined): SDKInfoBuilder {
|
||||
this._version = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
versionCode(versionCode: string | undefined): SDKInfoBuilder {
|
||||
this._versionCode = versionCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
hostname(hostname: string | undefined): SDKInfoBuilder {
|
||||
this._hostname = hostname;
|
||||
return this;
|
||||
}
|
||||
|
||||
sender(sender: string | undefined): SDKInfoBuilder {
|
||||
this._sender = sender;
|
||||
return this;
|
||||
}
|
||||
|
||||
build(): SDKInfo {
|
||||
return new SDKInfo({
|
||||
name: this._name,
|
||||
version: this._version,
|
||||
versionCode: this._versionCode,
|
||||
hostname: this._hostname,
|
||||
sender: this._sender,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class Target {
|
||||
telegram?: Telegram;
|
||||
discord?: Discord;
|
||||
sdkInfo?: SDKInfo;
|
||||
|
||||
constructor({
|
||||
telegram,
|
||||
discord,
|
||||
sdkInfo,
|
||||
}: {
|
||||
telegram?: Telegram;
|
||||
discord?: Discord;
|
||||
sdkInfo?: SDKInfo;
|
||||
}) {
|
||||
this.telegram = telegram;
|
||||
this.discord = discord;
|
||||
this.sdkInfo = sdkInfo;
|
||||
}
|
||||
|
||||
toMap(): Record<string, any> {
|
||||
return {
|
||||
telegram: this.telegram?.toMap(),
|
||||
discord: this.discord?.toMap(),
|
||||
sdk_info: this.sdkInfo?.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
merge(defaultTarget?: Target): void {
|
||||
if (!defaultTarget) return;
|
||||
this.telegram ||= defaultTarget.telegram;
|
||||
this.discord ||= defaultTarget.discord;
|
||||
}
|
||||
|
||||
static withTelegram(
|
||||
chatId: string,
|
||||
{
|
||||
token,
|
||||
parseMode,
|
||||
disabled,
|
||||
extras,
|
||||
}: {
|
||||
token?: string;
|
||||
parseMode?: TelegramParseMode;
|
||||
disabled?: boolean;
|
||||
extras?: any;
|
||||
} = {}
|
||||
): Target {
|
||||
return new Target({
|
||||
telegram: new Telegram({
|
||||
chatId,
|
||||
token,
|
||||
parseMode,
|
||||
disabled,
|
||||
extras,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
static withDiscord(
|
||||
webhookUrl: string,
|
||||
{
|
||||
webhookId,
|
||||
webhookToken,
|
||||
disabled,
|
||||
extras,
|
||||
}: {
|
||||
webhookId?: string;
|
||||
webhookToken?: string;
|
||||
disabled?: boolean;
|
||||
extras?: any;
|
||||
}
|
||||
): Target {
|
||||
return new Target({
|
||||
discord: new Discord({
|
||||
webhookUrl,
|
||||
webhookId,
|
||||
webhookToken,
|
||||
disabled,
|
||||
extras,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
static builder(): TargetBuilder {
|
||||
return new TargetBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
class TargetBuilder {
|
||||
private _telegram?: Telegram;
|
||||
private _discord?: Discord;
|
||||
private _sdkInfo?: SDKInfo;
|
||||
|
||||
constructor() { }
|
||||
|
||||
telegram(telegram?: Telegram): TargetBuilder {
|
||||
this._telegram = telegram;
|
||||
return this;
|
||||
}
|
||||
|
||||
discord(discord?: Discord): TargetBuilder {
|
||||
this._discord = discord;
|
||||
return this;
|
||||
}
|
||||
|
||||
sdkInfo(sdkInfo?: SDKInfo): TargetBuilder {
|
||||
this._sdkInfo = sdkInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
build(): Target {
|
||||
return new Target({
|
||||
telegram: this._telegram,
|
||||
discord: this._discord,
|
||||
sdkInfo: this._sdkInfo,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class Collector {
|
||||
id?: string;
|
||||
type?: string;
|
||||
source?: string;
|
||||
message?: string;
|
||||
data?: any;
|
||||
userAgent?: string;
|
||||
timestamp?: number;
|
||||
target?: Target;
|
||||
tags?: string[];
|
||||
|
||||
constructor({
|
||||
id,
|
||||
type,
|
||||
source,
|
||||
message,
|
||||
data,
|
||||
userAgent,
|
||||
timestamp,
|
||||
target,
|
||||
tags,
|
||||
}: {
|
||||
id?: string;
|
||||
type?: string;
|
||||
source?: string;
|
||||
message?: string;
|
||||
data?: any;
|
||||
userAgent?: string;
|
||||
timestamp?: number;
|
||||
target?: Target;
|
||||
tags?: string[];
|
||||
}) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.source = source;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
this.userAgent = userAgent;
|
||||
this.timestamp = timestamp;
|
||||
this.target = target;
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
getId(): string | undefined {
|
||||
if (!this.id) {
|
||||
this.id = generateUUID();
|
||||
}
|
||||
return this.id;
|
||||
}
|
||||
|
||||
getTimestamp(): number | undefined {
|
||||
if (!this.timestamp) {
|
||||
this.timestamp = Date.now();
|
||||
}
|
||||
return this.timestamp;
|
||||
}
|
||||
|
||||
toMap(): Record<string, any> {
|
||||
return {
|
||||
id: this.getId(),
|
||||
type: this.type,
|
||||
source: this.source,
|
||||
message: this.message,
|
||||
data: this.data,
|
||||
user_agent: this.userAgent,
|
||||
timestamp: this.getTimestamp(),
|
||||
target: this.target?.toMap(),
|
||||
tags: this.tags,
|
||||
};
|
||||
}
|
||||
|
||||
toJson(): string {
|
||||
return JSON.stringify(this.toMap());
|
||||
}
|
||||
|
||||
static builder(): CollectorBuilder {
|
||||
return new CollectorBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
class CollectorBuilder {
|
||||
private _id?: string;
|
||||
private _type?: string;
|
||||
private _source?: string;
|
||||
private _message?: string;
|
||||
private _data?: any;
|
||||
private _userAgent?: string;
|
||||
private _timestamp?: number;
|
||||
private _target?: Target;
|
||||
private _tags?: string[];
|
||||
|
||||
constructor() { }
|
||||
|
||||
id(id: string): CollectorBuilder {
|
||||
this._id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
type(type: string | CollectorType): CollectorBuilder {
|
||||
this._type = type?.toString();
|
||||
return this;
|
||||
}
|
||||
|
||||
source(source: string | CollectorSource): CollectorBuilder {
|
||||
this._source = source?.toString();
|
||||
return this;
|
||||
}
|
||||
|
||||
message(message: string): CollectorBuilder {
|
||||
this._message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
data(data: any): CollectorBuilder {
|
||||
this._data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
userAgent(userAgent: string): CollectorBuilder {
|
||||
this._userAgent = userAgent;
|
||||
return this;
|
||||
}
|
||||
|
||||
timestamp(timestamp: number): CollectorBuilder {
|
||||
this._timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
target(target: Target): CollectorBuilder {
|
||||
this._target = target;
|
||||
return this;
|
||||
}
|
||||
|
||||
tags(tags: string[]): CollectorBuilder {
|
||||
this._tags = tags;
|
||||
return this;
|
||||
}
|
||||
|
||||
build(): Collector {
|
||||
return new Collector({
|
||||
id: this._id,
|
||||
type: this._type,
|
||||
source: this._source,
|
||||
message: this._message,
|
||||
data: this._data,
|
||||
userAgent: this._userAgent,
|
||||
timestamp: this._timestamp,
|
||||
target: this._target,
|
||||
tags: this._tags,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class CollectorResponse {
|
||||
message?: string;
|
||||
id?: string;
|
||||
|
||||
constructor({ message, id }: { message?: string; id?: string }) {
|
||||
this.message = message;
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
class VLogsOptions {
|
||||
url?: string;
|
||||
appId?: string;
|
||||
apiKey?: string;
|
||||
connectionTimeout?: number;
|
||||
testConnection?: boolean;
|
||||
target?: Target;
|
||||
|
||||
constructor({
|
||||
url,
|
||||
appId,
|
||||
apiKey,
|
||||
connectionTimeout,
|
||||
testConnection,
|
||||
target,
|
||||
}: {
|
||||
url?: string;
|
||||
appId?: string;
|
||||
apiKey?: string;
|
||||
connectionTimeout?: number;
|
||||
testConnection?: boolean;
|
||||
target?: Target;
|
||||
}) {
|
||||
this.url = url;
|
||||
this.appId = appId;
|
||||
this.apiKey = apiKey;
|
||||
this.connectionTimeout = connectionTimeout;
|
||||
this.testConnection = testConnection;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
static builder(): VLogsOptionsBuilder {
|
||||
return new VLogsOptionsBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
class VLogsOptionsBuilder {
|
||||
private _url?: string;
|
||||
private _appId?: string;
|
||||
private _apiKey?: string;
|
||||
private _connectionTimeout?: number;
|
||||
private _testConnection?: boolean;
|
||||
private _target?: Target;
|
||||
|
||||
constructor() { }
|
||||
|
||||
url(url: string): VLogsOptionsBuilder {
|
||||
this._url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
appId(appId: string): VLogsOptionsBuilder {
|
||||
this._appId = appId;
|
||||
return this;
|
||||
}
|
||||
|
||||
apiKey(apiKey: string): VLogsOptionsBuilder {
|
||||
this._apiKey = apiKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
connectionTimeout(connectionTimeout: number): VLogsOptionsBuilder {
|
||||
this._connectionTimeout = connectionTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
testConnection(testConnection: boolean): VLogsOptionsBuilder {
|
||||
this._testConnection = testConnection;
|
||||
return this;
|
||||
}
|
||||
|
||||
target(target: Target): VLogsOptionsBuilder {
|
||||
this._target = target;
|
||||
return this;
|
||||
}
|
||||
|
||||
telegram(telegram: Telegram): VLogsOptionsBuilder {
|
||||
if (!this._target) {
|
||||
this._target = Target.builder().telegram(telegram).build();
|
||||
} else {
|
||||
this._target.telegram = telegram;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
discord(discord: Discord): VLogsOptionsBuilder {
|
||||
if (!this._target) {
|
||||
this._target = Target.builder().discord(discord).build();
|
||||
} else {
|
||||
this._target.discord = discord;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
build(): VLogsOptions {
|
||||
return new VLogsOptions({
|
||||
url: this._url,
|
||||
appId: this._appId,
|
||||
apiKey: this._apiKey,
|
||||
connectionTimeout: this._connectionTimeout,
|
||||
testConnection: this._testConnection,
|
||||
target: this._target,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export {
|
||||
Collector,
|
||||
// CollectorBuilder,
|
||||
CollectorResponse,
|
||||
Target,
|
||||
// TargetBuilder,
|
||||
Telegram,
|
||||
// TelegramBuilder,
|
||||
Discord,
|
||||
// DiscordBuilder,
|
||||
SDKInfo,
|
||||
// SDKInfoBuilder,
|
||||
VLogsOptions,
|
||||
// VLogsOptionsBuilder,
|
||||
|
||||
CollectorSource,
|
||||
CollectorType,
|
||||
TelegramParseMode,
|
||||
}
|
37
src/service.ts
Normal file
37
src/service.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { Collector, CollectorResponse } from './model';
|
||||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
|
||||
class VLogsService {
|
||||
private url: string;
|
||||
|
||||
constructor(baseUrl: string) {
|
||||
this.url = `${baseUrl}/api/v1/collector`;
|
||||
}
|
||||
|
||||
async post(body: any, headers?: any, timeout?: number): Promise<CollectorResponse> {
|
||||
const config: AxiosRequestConfig = {
|
||||
method: 'POST',
|
||||
url: this.url,
|
||||
data: body,
|
||||
headers: headers,
|
||||
timeout: timeout ? timeout * 1000 : undefined,
|
||||
};
|
||||
|
||||
const response = await axios(config);
|
||||
|
||||
if (
|
||||
response.status === 200 ||
|
||||
response.status === 201 ||
|
||||
response.status === 202
|
||||
) {
|
||||
return await response.data;
|
||||
} else {
|
||||
throw new Error(
|
||||
`Failed to post data to vlogs server with status code: ${response.status} and message: ${response.statusText}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export { VLogsService };
|
35
src/util.ts
Normal file
35
src/util.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export const getSystemHostname = () => {
|
||||
let name = 'localhost';
|
||||
if (typeof window !== 'undefined') {
|
||||
name = window.location.hostname;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
if (typeof process !== 'undefined') {
|
||||
// @ts-ignore
|
||||
name = process.env.HOSTNAME;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
export const getSystemUsername = () => {
|
||||
let name = 'unknown';
|
||||
if (typeof window !== 'undefined') {
|
||||
name = window.navigator.userAgent;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
if (typeof process !== 'undefined') {
|
||||
// @ts-ignore
|
||||
name = process.env.USER;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
export const generateUUID = () => {
|
||||
return uuidv4();
|
||||
}
|
86
src/vlgos.ts
Normal file
86
src/vlgos.ts
Normal file
@ -0,0 +1,86 @@
|
||||
import { Collector, CollectorResponse, SDKInfo, Target, VLogsOptions } from "./model";
|
||||
import { VLogsService } from "./service";
|
||||
import { getSystemHostname, getSystemUsername } from "./util";
|
||||
|
||||
export class VLogs {
|
||||
private static readonly _logger = console;
|
||||
private static readonly NAME = 'vlogs';
|
||||
private static readonly VERSION = '1.0.0';
|
||||
private static readonly VERSION_CODE = '1';
|
||||
private static readonly DEFAULT_VLOGS_URL = 'https://vlogs-sg1.onrender.com';
|
||||
private static readonly APP_ID_HEADER_PREFIX = 'x-app-id';
|
||||
private static readonly API_KEY_HEADER_PREFIX = 'x-api-key';
|
||||
private static readonly DEFAULT_CONNECT_TIMEOUT = 60; // seconds
|
||||
|
||||
private _options!: VLogsOptions;
|
||||
private _service!: VLogsService;
|
||||
|
||||
constructor(options: VLogsOptions) {
|
||||
if (!options.appId || !options.apiKey) {
|
||||
throw new Error('AppID and ApiKey are required');
|
||||
}
|
||||
|
||||
// Set default options
|
||||
this._options = options;
|
||||
this._options.url ??= VLogs.DEFAULT_VLOGS_URL;
|
||||
|
||||
// Initialize service
|
||||
this._service = new VLogsService(this._options.url);
|
||||
|
||||
VLogs._logger.log(`VLogs: Initialized AppID: ${this._options.appId} | SDK Version: ${VLogs.VERSION}-${VLogs.VERSION_CODE}`);
|
||||
}
|
||||
|
||||
async collect(request: Collector): Promise<CollectorResponse> {
|
||||
VLogs._logger.info(`VLogs: Collecting logs for ${request.getId()}`);
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
[VLogs.APP_ID_HEADER_PREFIX]: this._options.appId!,
|
||||
[VLogs.API_KEY_HEADER_PREFIX]: this._options.apiKey!,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
const hostname = getSystemHostname();
|
||||
const sender = getSystemUsername();
|
||||
const sdkInfo = SDKInfo.builder()
|
||||
.hostname(hostname)
|
||||
.sender(sender)
|
||||
.name(VLogs.NAME)
|
||||
.version(VLogs.VERSION)
|
||||
.versionCode(VLogs.VERSION_CODE)
|
||||
.build();
|
||||
|
||||
if (!request.target) {
|
||||
if (this._options.target) {
|
||||
request.target = this._options.target;
|
||||
} else {
|
||||
request.target = Target.builder().build();
|
||||
}
|
||||
} else {
|
||||
if (this._options.target) {
|
||||
request.target!.merge(this._options.target);
|
||||
}
|
||||
}
|
||||
|
||||
// Set SDK info to request
|
||||
request.target!.sdkInfo = sdkInfo;
|
||||
|
||||
// Append user agent to request
|
||||
request.userAgent ??= `vlogs-ts-sdk/${VLogs.VERSION}-${VLogs.VERSION_CODE} (${hostname})`;
|
||||
|
||||
const response = await this._service.post(request.toMap(), headers, this._options.connectionTimeout ?? VLogs.DEFAULT_CONNECT_TIMEOUT);
|
||||
return response;
|
||||
}
|
||||
|
||||
static create(options: VLogsOptions): VLogs {
|
||||
return new VLogs(options);
|
||||
}
|
||||
|
||||
static createWith(appId: string, apiKey: string): VLogs {
|
||||
return VLogs.create(
|
||||
VLogsOptions.builder()
|
||||
.apiKey(apiKey)
|
||||
.appId(appId)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
}
|
59
tests/vlogs.test.ts
Normal file
59
tests/vlogs.test.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { Collector, CollectorSource, CollectorType, VLogs, VLogsOptions } from '../src';
|
||||
|
||||
const APP_ID = '72bd14c306a91fa8a590330e3898ddcc';
|
||||
const API_KEY = 'vlogs_gX9WwSdKatMNdpUClLU0IfCx575tvdoeQ'
|
||||
|
||||
const sdk = VLogs.create(
|
||||
VLogsOptions.builder()
|
||||
.appId(APP_ID)
|
||||
.apiKey(API_KEY)
|
||||
// .target(Target.withTelegram("xxx"))
|
||||
.build()
|
||||
)
|
||||
|
||||
test('VLogs sdk should be defined', () => {
|
||||
expect(sdk).toBeDefined();
|
||||
});
|
||||
|
||||
test('VLogs sdk should be able to collect logs', async () => {
|
||||
const request = Collector.builder()
|
||||
.message('Hello from vlogs-ts-sdk')
|
||||
.type(CollectorType.Log)
|
||||
.source(CollectorSource.Web)
|
||||
.build();
|
||||
|
||||
const response = await sdk.collect(request);
|
||||
console.log("Request: ", request);
|
||||
console.log("Response: ", response);
|
||||
|
||||
expect(request.getId()).toBeDefined();
|
||||
expect(request.getId()).not.toBeNull();
|
||||
expect(request.getId()).toEqual(response.id);
|
||||
|
||||
expect(response).toBeDefined();
|
||||
expect(response.id).toBeDefined();
|
||||
expect(response.id).not.toBeNull();
|
||||
expect(response.id).not.toBe('');
|
||||
})
|
||||
|
||||
test('VLogs sdk should be able to collect logs with target', async () => {
|
||||
const request = Collector.builder()
|
||||
.message('Hello from vlogs-ts-sdk')
|
||||
.type(CollectorType.Log)
|
||||
.source(CollectorSource.Web)
|
||||
// .target(Target.withTelegram("xxx"))
|
||||
.build();
|
||||
|
||||
const response = await sdk.collect(request);
|
||||
console.log("Request: ", request);
|
||||
console.log("Response: ", response);
|
||||
|
||||
expect(request.getId()).toBeDefined();
|
||||
expect(request.getId()).not.toBeNull();
|
||||
expect(request.getId()).toEqual(response.id);
|
||||
|
||||
expect(response).toBeDefined();
|
||||
expect(response.id).toBeDefined();
|
||||
expect(response.id).not.toBeNull();
|
||||
expect(response.id).not.toBe('');
|
||||
})
|
12
tsconfig.json
Normal file
12
tsconfig.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"types": ["jest"]
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user