Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/isolates.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:mewe_maps/repositories/storage/storage_repository.dart';
import 'package:mewe_maps/services/firebase/firebase_initialization.dart';
import 'package:mewe_maps/utils/loggly_logger.dart';

Future<void> initializeIsolate() async {
WidgetsFlutterBinding.ensureInitialized();
Expand All @@ -25,6 +26,7 @@ Future<void> initializeIsolate() async {
exit(1);
};

initializeLogglyLogger();
await initializeFirebase();
await StorageRepository.initialize();
}
4 changes: 2 additions & 2 deletions lib/repositories/location/sharing_location_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class FirestoreSharingLocationRepository implements SharingLocationRepository {

@override
Future<void> uploadPosition(Position position, List<SharingSession> sessions) {
Logger.log(_TAG, 'Uploading position to ${sessions.length} sessions');
Logger.logOnline(_TAG, 'Uploading position to ${sessions.length} sessions');
List<Future> futures = [];
for (var session in sessions) {
final data = ShareData(
Expand All @@ -175,7 +175,7 @@ class FirestoreSharingLocationRepository implements SharingLocationRepository {
);
futures.add(_firestore.collection(FirestoreConstants.COLLECTION_SHARING_DATA).doc(data.sessionId).set(data.toJson()));
}
return Future.value();
return Future.wait(futures);
}

@override
Expand Down
22 changes: 22 additions & 0 deletions lib/services/http/loggly_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright MeWe 2025.
//
// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

import 'package:dio/dio.dart';
import 'package:retrofit/retrofit.dart';

part 'loggly_service.g.dart';

@RestApi()
abstract class LogglyService {
factory LogglyService(Dio dio, {String baseUrl}) = _LogglyService;

@POST("inputs/{token}/tag/{tags}/")
Future<void> sendLog(@Path("token") String token, @Path("tags") tags, @Body() Map<String, dynamic> logData);
}
10 changes: 5 additions & 5 deletions lib/services/location/location_sharing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import 'package:mewe_maps/utils/logger.dart';
const String _TAG = "shareMyLocationWithSessions";

Future<bool> shareMyLocationWithSessions() async {
Logger.log(_TAG, "shareMyLocationWithSessions");
Logger.logOnline(_TAG, "shareMyLocationWithSessions");
Comment thread
dmytro-mewe marked this conversation as resolved.
Outdated

final userId = StorageRepository.user?.userId;
if (userId != null) {
Expand All @@ -27,16 +27,16 @@ Future<bool> shareMyLocationWithSessions() async {
final sessions = await sharingRepository.getSharingSessionsAsOwner(userId);
if (sessions != null && sessions.isNotEmpty) {
await sharingRepository.uploadPosition(lastPosition, sessions);
Logger.log(_TAG, "success");
await Logger.logOnline(_TAG, "success");
return true;
} else {
Logger.log(_TAG, "failed (no sessions)");
await Logger.logOnline(_TAG, "failed (no sessions)");
}
} else {
Logger.log(_TAG, "failed (no last position)");
await Logger.logOnline(_TAG, "failed (no last position)");
}
} else {
Logger.log(_TAG, "failed (no current user)");
await Logger.logOnline(_TAG, "failed (no current user)");
}
return false;
}
6 changes: 3 additions & 3 deletions lib/services/workmanager/workmanager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void workmanagerCallback() async {
await initializeIsolate();

Workmanager().executeTask((task, inputData) async {
Logger.log(_TAG, "executeTask $task");
Logger.logOnline(_TAG, "executeTask $task");

if (task == _PERIODIC_SHARE_LOCATION_TASK) {
await shareMyLocationWithSessions();
Expand All @@ -45,10 +45,10 @@ Future<void> registerPeriodicShareMyLocationWithSessions() async {
_PERIODIC_SHARE_LOCATION_TASK,
frequency: const Duration(minutes: 15),
);
Logger.log(_TAG, "registerPeriodicShareMyLocationWithSessions success");
Logger.logOnline(_TAG, "registerPeriodicShareMyLocationWithSessions success");
}

Future<void> registerStopPreciseTrackingOnNoSessions() async {
await Workmanager().registerOneOffTask(_STOP_TRACKING_NO_SESSIONS_TASK, _STOP_TRACKING_NO_SESSIONS_TASK);
Logger.log(_TAG, "registerStopPreciseTrackingOnNoSessions success");
Logger.logOnline(_TAG, "registerStopPreciseTrackingOnNoSessions success");
}
16 changes: 13 additions & 3 deletions lib/utils/logger.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,21 @@
//
// You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

import 'package:flutter/foundation.dart';
import 'package:mewe_maps/utils/loggly_logger.dart';

class Logger {
static bool LOG_DIO = false;
static bool LOG_DIO = true;

static void log(String tag, String text) {
final pattern = RegExp('.{1,800}'); // 800 is the size of each chunk
pattern.allMatches(text).forEach((match) => print("MEWE_MAPS: $tag: ${match.group(0)}"));
if (kDebugMode) {
final pattern = RegExp('.{1,800}'); // 800 is the size of each chunk
pattern.allMatches(text).forEach((match) => print("MEWE_MAPS: $tag: ${match.group(0)}"));
}
}

static Future<void> logOnline(String tag, String text, {Map<String, dynamic>? params}) async {
LogglyLogger.instance.log(text, tag: tag, params: params);
log(tag, text);
}
}
74 changes: 74 additions & 0 deletions lib/utils/loggly_logger.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright MeWe 2025.
//
// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:mewe_maps/repositories/storage/storage_repository.dart';
import 'package:mewe_maps/services/http/loggly_service.dart';
import 'package:mewe_maps/utils/logger.dart';

const _TAG = "LogglyLogger";

void initializeLogglyLogger() {
LogglyLogger.instance.configure(token: dotenv.env["LOGGLY_TOKEN"], baseUrl: "http://logs-01.loggly.com/");
}

class LogglyLogger {
static final LogglyLogger instance = LogglyLogger._internal();

LogglyService? _logglyService;
String? _token;

LogglyLogger._internal();

void configure({required String? token, required String baseUrl, String? tag}) {
_token = token;
final dio = Dio();
_logglyService = LogglyService(dio, baseUrl: baseUrl);
}

void log(String message, {String? tag, String level = 'info', Map<String, dynamic>? params}) {
final Map<String, dynamic> payload = {
'level': level,
'message': message,
'userId': StorageRepository.user?.userId,
'params': params ?? {},
};

final tags = createTags(tag).join(',');

_logglyService?.sendLog(_token!, tags, payload).then((_) {
Logger.log(_TAG, 'Loggly log sent: $message');
}).catchError((error) {
Logger.log(_TAG, 'Loggly error: $error');
});
}

List<String> createTags(String? tag) {
Comment thread
dmytro-mewe marked this conversation as resolved.
Outdated
List<String> tags = [];
if (tag != null) {
tags.add(tag);
}
if (Platform.isIOS) {
tags.add("ios");
} else if (Platform.isAndroid) {
tags.add("android");
}
if (kDebugMode) {
tags.add("debug");
} else {
tags.add("release");
}
return tags;
}
}