1
0
mirror of https://github.com/GitJournal/GitJournal.git synced 2025-08-06 15:21:21 +08:00

Analytics: Send to backend when possible

This commit is contained in:
Vishesh Handa
2021-08-12 00:09:12 +02:00
parent 9efc8cfcfa
commit 103197b886
4 changed files with 80 additions and 35 deletions

@ -6,7 +6,10 @@ import 'package:uuid/uuid.dart';
import 'package:gitjournal/features.dart';
import 'package:gitjournal/logger/logger.dart';
import 'device_info.dart';
import 'generated/analytics.pb.dart' as pb;
import 'network.dart';
import 'package_info.dart';
import 'storage.dart';
enum Event {
@ -114,6 +117,8 @@ class Analytics {
await storage.logEvent(_buildEvent(name, parameters));
analyticsCallback(name, parameters);
await _sendAnalytics();
}
Future<void> setCurrentScreen({required String screenName}) async {
@ -138,6 +143,39 @@ class Analytics {
userFirstTouchTimestamp: null,
);
}
Future<void> _sendAnalytics() async {
if (!enabled) {
return;
}
var oldestEvent = await storage.oldestEvent();
if (DateTime.now().difference(oldestEvent) < const Duration(hours: 1)) {
return;
}
await storage.fetchAll((events) async {
var msg = pb.AnalyticsMessage(
appId: 'io.gitjournal',
deviceInfo: await buildDeviceInfo(),
packageInfo: await buildPackageInfo(),
events: events,
);
Log.i("Sending ${events.length} events");
var result = await sendAnalytics(msg);
if (result.isFailure) {
Log.e(
"Failed to send Analytics",
ex: result.error,
stacktrace: result.stackTrace,
);
return false;
}
Log.i("Sent ${events.length} Analytics Events");
return true;
});
}
}
void logEvent(Event event, {Map<String, String> parameters = const {}}) {
@ -149,3 +187,7 @@ String _eventToString(Event e) {
var str = e.toString().substring('Event.'.length);
return ReCase(str).snakeCase;
}
// FIXME: Discard the old analytics, if there are way too many!
// TODO: Take network connectivity into account
// TODO: Take connection type (wifi vs mobile) into account

@ -1,13 +1,17 @@
import 'package:fixnum/fixnum.dart';
import 'package:dart_git/utils/result.dart';
import 'package:grpc/grpc.dart';
import 'package:gitjournal/analytics/generated/analytics.pbgrpc.dart';
import 'generated/analytics.pb.dart' as pb;
Future<void> main(List<String> args) async {
const _url = 'analyticsbackend-wetu2tkdpq-ew.a.run.app';
const _port = 444;
const _timeout = Duration(seconds: 30);
Future<Result<void>> sendAnalytics(pb.AnalyticsMessage msg) async {
final channel = ClientChannel(
'analyticsbackend-wetu2tkdpq-ew.a.run.app',
port: 443,
_url,
port: _port,
options: ChannelOptions(
// credentials: const ChannelCredentials.insecure(),
credentials: const ChannelCredentials.secure(),
@ -18,38 +22,21 @@ Future<void> main(List<String> args) async {
),
);
final stub = AnalyticsServiceClient(channel);
final client = AnalyticsServiceClient(channel);
try {
var dt = DateTime.now().add(const Duration(days: -1));
var ev = pb.Event(
name: 'test',
date: Int64(dt.millisecondsSinceEpoch ~/ 1000),
params: {'a': 'hello'},
pseudoId: 'id',
userProperties: {'b': 'c'},
sessionID: 'session',
var call = client.sendData(
msg,
options: CallOptions(
timeout: _timeout,
compression: const GzipCodec(),
),
);
var request = AnalyticsMessage(
appId: 'io.gitjournal',
events: [ev],
);
print("Sending ${request.toDebugString()}");
var call = stub.sendData(
request,
options: CallOptions(timeout: const Duration(seconds: 10)),
);
call.headers.then((headers) {
print('Received header metadata: $headers');
});
call.trailers.then((trailers) {
print('Received trailer metadata: $trailers');
});
var response = await call;
print('Greeter client received: $response');
} catch (e) {
print('Caught error: $e');
return;
await call;
} on Exception catch (e, st) {
await channel.shutdown();
return Result.fail(e, st);
}
await channel.shutdown();
return Result(null);
}

@ -0,0 +1,14 @@
import 'package:package_info_plus/package_info_plus.dart';
import 'generated/analytics.pb.dart' as pb;
Future<pb.PackageInfo> buildPackageInfo() async {
var info = await PackageInfo.fromPlatform();
return pb.PackageInfo(
appName: info.appName,
packageName: info.packageName,
version: info.version,
buildNumber: info.buildNumber,
buildSignature: info.buildSignature,
);
}

@ -15,7 +15,7 @@ import 'package:quick_actions/quick_actions.dart';
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:universal_io/io.dart' show Platform;
import 'package:universal_io/io.dart' show Directory, Platform;
import 'package:gitjournal/analytics/analytics.dart';
import 'package:gitjournal/analytics/route_observer.dart';
@ -131,8 +131,10 @@ class JournalApp extends StatefulWidget {
var supportDir = await getApplicationSupportDirectory();
var analyticsStorage = p.join(supportDir.path, 'analytics');
await Directory(analyticsStorage).create(recursive: true);
Log.d("Analytics Collection: $enabled");
Log.d("Analytics Storage: $analyticsStorage");
var analytics = Analytics.init(
enable: enabled,
pref: pref,