Add collect the logs
This commit is contained in:
commit
467d1c6edf
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# https://dart.dev/guides/libraries/private-files
|
||||||
|
# Created by `dart pub`
|
||||||
|
.dart_tool/
|
||||||
|
|
||||||
|
# Avoid committing pubspec.lock for library packages; see
|
||||||
|
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||||
|
pubspec.lock
|
4
CHANGELOG.md
Normal file
4
CHANGELOG.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
## 1.0.0
|
||||||
|
|
||||||
|
- Initial version.
|
||||||
|
- Add collect the logs.
|
32
README.md
Normal file
32
README.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# vLogs SDK for Dart
|
||||||
|
|
||||||
|
A simple way to collect logs and send to the server via simple SDK.
|
||||||
|
|
||||||
|
- [x] Collect the logs
|
||||||
|
- [ ] Support local retries
|
||||||
|
|
||||||
|
## Usages
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'package:vlogs/vlogs.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
final APP_ID = "xxx";
|
||||||
|
final API_KEY = "vlogs_xxx";
|
||||||
|
|
||||||
|
final sdk = VLogs.create(APP_ID, API_KEY);
|
||||||
|
|
||||||
|
var request = CollectorRequest.builder()
|
||||||
|
.message("Hello World")
|
||||||
|
.source(CollectorSource.mobile.name)
|
||||||
|
.type(CollectorType.log.name)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var response = await sdk.collect(request);
|
||||||
|
print("Response: ${response.toJson()}");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
- Sambo Chea <sombochea@cubetiqs.com>
|
30
analysis_options.yaml
Normal file
30
analysis_options.yaml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# This file configures the static analysis results for your project (errors,
|
||||||
|
# warnings, and lints).
|
||||||
|
#
|
||||||
|
# This enables the 'recommended' set of lints from `package:lints`.
|
||||||
|
# This set helps identify many issues that may lead to problems when running
|
||||||
|
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
|
||||||
|
# style and format.
|
||||||
|
#
|
||||||
|
# If you want a smaller set of lints you can change this to specify
|
||||||
|
# 'package:lints/core.yaml'. These are just the most critical lints
|
||||||
|
# (the recommended set includes the core lints).
|
||||||
|
# The core lints are also what is used by pub.dev for scoring packages.
|
||||||
|
|
||||||
|
include: package:lints/recommended.yaml
|
||||||
|
|
||||||
|
# Uncomment the following section to specify additional rules.
|
||||||
|
|
||||||
|
# linter:
|
||||||
|
# rules:
|
||||||
|
# - camel_case_types
|
||||||
|
|
||||||
|
# analyzer:
|
||||||
|
# exclude:
|
||||||
|
# - path/to/excluded/files/**
|
||||||
|
|
||||||
|
# For more information about the core and recommended set of lints, see
|
||||||
|
# https://dart.dev/go/core-lints
|
||||||
|
|
||||||
|
# For additional information about configuring this file, see
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
19
example/vlogs_example.dart
Normal file
19
example/vlogs_example.dart
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// ignore_for_file: non_constant_identifier_names
|
||||||
|
|
||||||
|
import 'package:vlogs/vlogs.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
final APP_ID = "72bd14c306a91fa8a590330e3898ddcc";
|
||||||
|
final API_KEY = "vlogs_gX9WwSdKatMNdpUClLU0IfCx575tvdoeQ";
|
||||||
|
|
||||||
|
final sdk = VLogs.create(APP_ID, API_KEY);
|
||||||
|
|
||||||
|
var request = CollectorRequest.builder()
|
||||||
|
.message("Hello World")
|
||||||
|
.source(CollectorSource.mobile.name)
|
||||||
|
.type(CollectorType.log.name)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var response = await sdk.collect(request);
|
||||||
|
print("Response: ${response.toJson()}");
|
||||||
|
}
|
88
lib/src/base.dart
Normal file
88
lib/src/base.dart
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// ignore_for_file: non_constant_identifier_names
|
||||||
|
|
||||||
|
import 'package:logger/logger.dart';
|
||||||
|
import 'package:vlogs/src/model.dart';
|
||||||
|
import 'package:vlogs/src/service.dart';
|
||||||
|
import 'package:vlogs/src/util.dart';
|
||||||
|
|
||||||
|
class VLogs {
|
||||||
|
static final _logger = Logger();
|
||||||
|
static final String NAME = 'vlogs';
|
||||||
|
static final String VERSION = '1.0.0';
|
||||||
|
static final String VERSION_CODE = '1';
|
||||||
|
static final String DEFAULT_VLOGS_URL = "https://vlogs-sg1.onrender.com";
|
||||||
|
static final String APP_ID_HEADER_PREFIX = "x-app-id";
|
||||||
|
static final String API_KEY_HEADER_PREFIX = "x-api-key";
|
||||||
|
static final int DEFAULT_CONNECT_TIMEOUT = 60; // seconds
|
||||||
|
|
||||||
|
late String _baseUrl;
|
||||||
|
late String _appId;
|
||||||
|
late String _apiKey;
|
||||||
|
|
||||||
|
late VLogsService _service;
|
||||||
|
|
||||||
|
VLogs(VLogsOptions options) {
|
||||||
|
_baseUrl = options.url ?? DEFAULT_VLOGS_URL;
|
||||||
|
if (options.appId == null || options.apiKey == null) {
|
||||||
|
throw Exception("AppId and ApiKey are required");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.apiKey!.isEmpty || options.appId!.isEmpty) {
|
||||||
|
throw Exception("AppId and ApiKey are required");
|
||||||
|
}
|
||||||
|
_appId = options.appId!;
|
||||||
|
_apiKey = options.apiKey!;
|
||||||
|
|
||||||
|
_service = VLogsService(_baseUrl);
|
||||||
|
|
||||||
|
_logger.i("VLogs: Initialized AppID: $_appId | SDK Version: $VERSION-$VERSION_CODE");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<CollectorResponse> collect(CollectorRequest request) async {
|
||||||
|
var headers = {
|
||||||
|
APP_ID_HEADER_PREFIX: _appId,
|
||||||
|
API_KEY_HEADER_PREFIX: _apiKey,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
};
|
||||||
|
|
||||||
|
var hostname = Util.getSystemHostname();
|
||||||
|
var sender = Util.getSystemUsername();
|
||||||
|
var sdkInfo = SDKInfo.builder()
|
||||||
|
.hostname(hostname)
|
||||||
|
.sender(sender)
|
||||||
|
.name(VLogs.NAME)
|
||||||
|
.version(VLogs.VERSION)
|
||||||
|
.versionCode(VLogs.VERSION_CODE)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
if (request.target == null) {
|
||||||
|
request.target = Target.builder().sdkInfo(sdkInfo).build();
|
||||||
|
} else {
|
||||||
|
request.target!.sdkInfo = sdkInfo;
|
||||||
|
}
|
||||||
|
request.userAgent ??= "vlogs-dart-sdk/$VERSION-$VERSION_CODE ($hostname)";
|
||||||
|
|
||||||
|
var response = await _service.post(request.toJson(), headers: headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
void collectAsync(CollectorRequest request) async {
|
||||||
|
try {
|
||||||
|
var response = await collect(request);
|
||||||
|
_logger.i("VLogs: ${response.message}");
|
||||||
|
} catch (e) {
|
||||||
|
_logger.e("VLogs: ${e.toString()}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static VLogs createWithOptions(VLogsOptions options) {
|
||||||
|
return VLogs(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VLogs create(String appId, String apiKey) {
|
||||||
|
return createWithOptions(VLogsOptions(
|
||||||
|
appId: appId,
|
||||||
|
apiKey: apiKey,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
487
lib/src/model.dart
Normal file
487
lib/src/model.dart
Normal file
@ -0,0 +1,487 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
|
enum CollectorType { error, event, metric, trace, log, span }
|
||||||
|
|
||||||
|
enum CollectorSource { web, mobile, server, desktop, iot, other }
|
||||||
|
|
||||||
|
enum TelegramParseMode { markdown, markdownV2, html }
|
||||||
|
|
||||||
|
class Telegram {
|
||||||
|
String? token;
|
||||||
|
String? chatId;
|
||||||
|
TelegramParseMode? parseMode;
|
||||||
|
bool? disabled;
|
||||||
|
|
||||||
|
Telegram({
|
||||||
|
this.token,
|
||||||
|
this.chatId,
|
||||||
|
this.parseMode,
|
||||||
|
this.disabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'token': token,
|
||||||
|
'chat_id': chatId,
|
||||||
|
'parse_mode': parseMode,
|
||||||
|
'disabled': disabled,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static TelegramBuilder builder() {
|
||||||
|
return TelegramBuilder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TelegramBuilder {
|
||||||
|
String? _token;
|
||||||
|
String? _chatId;
|
||||||
|
TelegramParseMode? _parseMode;
|
||||||
|
bool? _disabled;
|
||||||
|
|
||||||
|
TelegramBuilder();
|
||||||
|
|
||||||
|
TelegramBuilder token(String? token) {
|
||||||
|
_token = token;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TelegramBuilder chatId(String? chatId) {
|
||||||
|
_chatId = chatId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TelegramBuilder parseMode(TelegramParseMode? parseMode) {
|
||||||
|
_parseMode = parseMode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TelegramBuilder disabled(bool? disabled) {
|
||||||
|
_disabled = disabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Telegram build() {
|
||||||
|
return Telegram(
|
||||||
|
token: _token,
|
||||||
|
chatId: _chatId,
|
||||||
|
parseMode: _parseMode,
|
||||||
|
disabled: _disabled,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Discord {
|
||||||
|
String? webhookId;
|
||||||
|
String? webhookToken;
|
||||||
|
String? webhookUrl;
|
||||||
|
bool? disabled;
|
||||||
|
|
||||||
|
Discord({
|
||||||
|
this.webhookId,
|
||||||
|
this.webhookToken,
|
||||||
|
this.webhookUrl,
|
||||||
|
this.disabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
Discord._builder(DiscordBuilder builder)
|
||||||
|
: webhookId = builder._webhookId,
|
||||||
|
webhookToken = builder._webhookToken,
|
||||||
|
webhookUrl = builder._webhookUrl,
|
||||||
|
disabled = builder._disabled;
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'webhook_id': webhookId,
|
||||||
|
'webhook_token': webhookToken,
|
||||||
|
'webhook_url': webhookUrl,
|
||||||
|
'disabled': disabled,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static DiscordBuilder builder() {
|
||||||
|
return DiscordBuilder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiscordBuilder {
|
||||||
|
String? _webhookId;
|
||||||
|
String? _webhookToken;
|
||||||
|
String? _webhookUrl;
|
||||||
|
bool? _disabled;
|
||||||
|
|
||||||
|
DiscordBuilder();
|
||||||
|
|
||||||
|
DiscordBuilder webhookId(String? webhookId) {
|
||||||
|
_webhookId = webhookId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscordBuilder webhookToken(String? webhookToken) {
|
||||||
|
_webhookToken = webhookToken;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscordBuilder webhookUrl(String? webhookUrl) {
|
||||||
|
_webhookUrl = webhookUrl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscordBuilder disabled(bool? disabled) {
|
||||||
|
_disabled = disabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Discord build() {
|
||||||
|
return Discord._builder(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SDKInfo {
|
||||||
|
String? name;
|
||||||
|
String? version;
|
||||||
|
String? versionCode;
|
||||||
|
String? hostname;
|
||||||
|
String? sender;
|
||||||
|
|
||||||
|
SDKInfo({
|
||||||
|
this.name,
|
||||||
|
this.version,
|
||||||
|
this.versionCode,
|
||||||
|
this.hostname,
|
||||||
|
this.sender,
|
||||||
|
});
|
||||||
|
|
||||||
|
SDKInfo._builder(SDKInfoBuilder builder)
|
||||||
|
: name = builder._name,
|
||||||
|
version = builder._version,
|
||||||
|
versionCode = builder._versionCode,
|
||||||
|
hostname = builder._hostname,
|
||||||
|
sender = builder._sender;
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'name': name,
|
||||||
|
'version': version,
|
||||||
|
'version_code': versionCode,
|
||||||
|
'hostname': hostname,
|
||||||
|
'sender': sender,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDKInfoBuilder builder() {
|
||||||
|
return SDKInfoBuilder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SDKInfoBuilder {
|
||||||
|
String? _name;
|
||||||
|
String? _version;
|
||||||
|
String? _versionCode;
|
||||||
|
String? _hostname;
|
||||||
|
String? _sender;
|
||||||
|
|
||||||
|
SDKInfoBuilder();
|
||||||
|
|
||||||
|
SDKInfoBuilder name(String? name) {
|
||||||
|
_name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDKInfoBuilder version(String? version) {
|
||||||
|
_version = version;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDKInfoBuilder versionCode(String? versionCode) {
|
||||||
|
_versionCode = versionCode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDKInfoBuilder hostname(String? hostname) {
|
||||||
|
_hostname = hostname;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDKInfoBuilder sender(String? sender) {
|
||||||
|
_sender = sender;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDKInfo build() {
|
||||||
|
return SDKInfo._builder(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
Telegram? telegram;
|
||||||
|
Discord? discord;
|
||||||
|
SDKInfo? sdkInfo;
|
||||||
|
|
||||||
|
Target({
|
||||||
|
this.telegram,
|
||||||
|
this.discord,
|
||||||
|
this.sdkInfo,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'telegram': telegram?.toMap(),
|
||||||
|
'discord': discord?.toMap(),
|
||||||
|
'sdk_info': sdkInfo?.toMap(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static TargetBuilder builder() {
|
||||||
|
return TargetBuilder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TargetBuilder {
|
||||||
|
Telegram? _telegram;
|
||||||
|
Discord? _discord;
|
||||||
|
SDKInfo? _sdkInfo;
|
||||||
|
|
||||||
|
TargetBuilder();
|
||||||
|
|
||||||
|
TargetBuilder telegram(Telegram? telegram) {
|
||||||
|
_telegram = telegram;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetBuilder discord(Discord? discord) {
|
||||||
|
_discord = discord;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetBuilder sdkInfo(SDKInfo? sdkInfo) {
|
||||||
|
_sdkInfo = sdkInfo;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Target build() {
|
||||||
|
return Target(
|
||||||
|
telegram: _telegram,
|
||||||
|
discord: _discord,
|
||||||
|
sdkInfo: _sdkInfo,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CollectorRequest {
|
||||||
|
String? id;
|
||||||
|
String? type;
|
||||||
|
String? source;
|
||||||
|
String? message;
|
||||||
|
dynamic data;
|
||||||
|
String? userAgent;
|
||||||
|
int? timestamp;
|
||||||
|
Target? target;
|
||||||
|
List<String>? tags;
|
||||||
|
|
||||||
|
CollectorRequest(
|
||||||
|
{this.id,
|
||||||
|
this.type,
|
||||||
|
this.source,
|
||||||
|
this.message,
|
||||||
|
this.data,
|
||||||
|
this.userAgent,
|
||||||
|
this.timestamp,
|
||||||
|
this.target,
|
||||||
|
this.tags});
|
||||||
|
|
||||||
|
String? getId() {
|
||||||
|
id ??= Uuid().v4();
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int? getTimestamp() {
|
||||||
|
timestamp ??= DateTime.now().millisecondsSinceEpoch;
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'id': getId(),
|
||||||
|
'type': type,
|
||||||
|
'source': source,
|
||||||
|
'message': message,
|
||||||
|
'data': data,
|
||||||
|
'user_agent': userAgent,
|
||||||
|
'timestamp': getTimestamp(),
|
||||||
|
'target': target?.toMap(),
|
||||||
|
'tags': tags,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
String toJson() => json.encode(toMap());
|
||||||
|
|
||||||
|
static CollectorRequestBuilder builder() {
|
||||||
|
return CollectorRequestBuilder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CollectorRequestBuilder {
|
||||||
|
String? _id;
|
||||||
|
String? _type;
|
||||||
|
String? _source;
|
||||||
|
String? _message;
|
||||||
|
dynamic _data;
|
||||||
|
String? _userAgent;
|
||||||
|
int? _timestamp;
|
||||||
|
Target? _target;
|
||||||
|
List<String>? _tags;
|
||||||
|
|
||||||
|
CollectorRequestBuilder();
|
||||||
|
|
||||||
|
CollectorRequestBuilder id(String? id) {
|
||||||
|
_id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectorRequestBuilder type(String? type) {
|
||||||
|
_type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectorRequestBuilder source(String? source) {
|
||||||
|
_source = source;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectorRequestBuilder message(String? message) {
|
||||||
|
_message = message;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectorRequestBuilder data(dynamic data) {
|
||||||
|
_data = data;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectorRequestBuilder userAgent(String? userAgent) {
|
||||||
|
_userAgent = userAgent;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectorRequestBuilder timestamp(int? timestamp) {
|
||||||
|
_timestamp = timestamp;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectorRequestBuilder target(Target? target) {
|
||||||
|
_target = target;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectorRequestBuilder tags(List<String>? tags) {
|
||||||
|
_tags = tags;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectorRequest build() {
|
||||||
|
return CollectorRequest(
|
||||||
|
id: _id,
|
||||||
|
type: _type,
|
||||||
|
source: _source,
|
||||||
|
message: _message,
|
||||||
|
data: _data,
|
||||||
|
userAgent: _userAgent,
|
||||||
|
timestamp: _timestamp,
|
||||||
|
target: _target,
|
||||||
|
tags: _tags,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CollectorResponse {
|
||||||
|
String? message;
|
||||||
|
String? id;
|
||||||
|
|
||||||
|
CollectorResponse({this.message, this.id});
|
||||||
|
|
||||||
|
bool get isSuccess => message == 'ok';
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'id': id,
|
||||||
|
'message': message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
String toJson() => json.encode(toMap());
|
||||||
|
|
||||||
|
factory CollectorResponse.fromMap(Map<String, dynamic> map) {
|
||||||
|
return CollectorResponse(
|
||||||
|
message: map['message'],
|
||||||
|
id: map['id'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory CollectorResponse.fromJson(String source) =>
|
||||||
|
CollectorResponse.fromMap(json.decode(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
class VLogsOptions {
|
||||||
|
String? url;
|
||||||
|
String? appId;
|
||||||
|
String? apiKey;
|
||||||
|
int? connectionTimeout;
|
||||||
|
bool? testConnection;
|
||||||
|
|
||||||
|
VLogsOptions({
|
||||||
|
this.url,
|
||||||
|
this.appId,
|
||||||
|
this.apiKey,
|
||||||
|
this.connectionTimeout,
|
||||||
|
this.testConnection,
|
||||||
|
});
|
||||||
|
|
||||||
|
VLogsOptions._builder(VLogsOptionsBuilder builder)
|
||||||
|
: url = builder._url,
|
||||||
|
appId = builder._appId,
|
||||||
|
apiKey = builder._apiKey,
|
||||||
|
connectionTimeout = builder._connectionTimeout,
|
||||||
|
testConnection = builder._testConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
class VLogsOptionsBuilder {
|
||||||
|
String? _url;
|
||||||
|
String? _appId;
|
||||||
|
String? _apiKey;
|
||||||
|
int? _connectionTimeout;
|
||||||
|
bool? _testConnection;
|
||||||
|
|
||||||
|
VLogsOptionsBuilder();
|
||||||
|
|
||||||
|
VLogsOptionsBuilder url(String? url) {
|
||||||
|
_url = url;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VLogsOptionsBuilder appId(String? appId) {
|
||||||
|
_appId = appId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VLogsOptionsBuilder apiKey(String? apiKey) {
|
||||||
|
_apiKey = apiKey;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VLogsOptionsBuilder connectionTimeout(int? connectionTimeout) {
|
||||||
|
_connectionTimeout = connectionTimeout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VLogsOptionsBuilder testConnection(bool? testConnection) {
|
||||||
|
_testConnection = testConnection;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VLogsOptions build() {
|
||||||
|
return VLogsOptions._builder(this);
|
||||||
|
}
|
||||||
|
}
|
32
lib/src/service.dart
Normal file
32
lib/src/service.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import 'package:vlogs/src/model.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
|
class VLogsService {
|
||||||
|
late final String url;
|
||||||
|
|
||||||
|
VLogsService(String baseUrl) {
|
||||||
|
url = '$baseUrl/api/v1/collector';
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<CollectorResponse> post(String body, {headers}) async {
|
||||||
|
var request = http.Request('POST', Uri.parse(url));
|
||||||
|
request.body = body;
|
||||||
|
// print("Request Body: ${request.body}");
|
||||||
|
|
||||||
|
if (headers != null) {
|
||||||
|
request.headers.addAll(headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = await request.send();
|
||||||
|
|
||||||
|
if (response.statusCode == 200 ||
|
||||||
|
response.statusCode == 201 ||
|
||||||
|
response.statusCode == 202) {
|
||||||
|
var json = await response.stream.bytesToString();
|
||||||
|
return CollectorResponse.fromJson(json);
|
||||||
|
} else {
|
||||||
|
throw Exception(
|
||||||
|
'Failed to post data to vlogs server with status code: ${response.statusCode}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
lib/src/util.dart
Normal file
26
lib/src/util.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
class Util {
|
||||||
|
static String? toJSON(dynamic data) {
|
||||||
|
try {
|
||||||
|
return jsonEncode(data);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getSystemHostname() {
|
||||||
|
String name = Platform.localHostname;
|
||||||
|
|
||||||
|
if (name.isEmpty) {
|
||||||
|
name = 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getSystemUsername() {
|
||||||
|
return Platform.environment['USER'] ?? 'unknown';
|
||||||
|
}
|
||||||
|
}
|
4
lib/vlogs.dart
Normal file
4
lib/vlogs.dart
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
library;
|
||||||
|
|
||||||
|
export 'src/base.dart';
|
||||||
|
export 'src/model.dart';
|
16
pubspec.yaml
Normal file
16
pubspec.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
name: vlogs
|
||||||
|
description: A simple way to collect logs and send to the server via simple SDK.
|
||||||
|
version: 1.0.0
|
||||||
|
repository: https://github.com/CUBETIQ/vlogs_sdk_dart.git
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ^3.0.2
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
http:
|
||||||
|
uuid:
|
||||||
|
logger:
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
lints: ^2.0.0
|
||||||
|
test: ^1.21.0
|
29
test/vlogs_test.dart
Normal file
29
test/vlogs_test.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// ignore_for_file: non_constant_identifier_names
|
||||||
|
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:vlogs/src/model.dart';
|
||||||
|
import 'package:vlogs/vlogs.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
final APP_ID = "72bd14c306a91fa8a590330e3898ddcc";
|
||||||
|
final API_KEY = "vlogs_gX9WwSdKatMNdpUClLU0IfCx575tvdoeQ";
|
||||||
|
|
||||||
|
group('A group of tests', () {
|
||||||
|
final sdk = VLogs.create(APP_ID, API_KEY);
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
// Additional setup goes here.
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Emit the logs to collector', () async {
|
||||||
|
var request = CollectorRequest.builder()
|
||||||
|
.message("Hello World")
|
||||||
|
.source(CollectorSource.mobile.name)
|
||||||
|
.type(CollectorType.log.name)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var response = await sdk.collect(request);
|
||||||
|
expect(response.id, request.getId());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user