Use the logging package, and log from RPC.

This commit is contained in:
Dain Nilsson 2021-11-23 13:02:05 +01:00
parent d9b5cdc951
commit 064fb038e6
No known key found for this signature in database
GPG Key ID: F04367096FBA95E8
7 changed files with 88 additions and 22 deletions

View File

@ -1,14 +1,16 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:developer' as developer;
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:logging/logging.dart';
import '../../core/rpc.dart'; import '../../core/rpc.dart';
import '../../core/state.dart'; import '../../core/state.dart';
import 'models.dart'; import 'models.dart';
final log = Logger('app.state');
final attachedDevicesProvider = final attachedDevicesProvider =
StateNotifierProvider<AttachedDeviceNotifier, List<DeviceNode>>( StateNotifierProvider<AttachedDeviceNotifier, List<DeviceNode>>(
(ref) => AttachedDeviceNotifier(ref.watch(rpcProvider))); (ref) => AttachedDeviceNotifier(ref.watch(rpcProvider)));
@ -32,8 +34,7 @@ class AttachedDeviceNotifier extends StateNotifier<List<DeviceNode>> {
if (_usbState != scan['state']) { if (_usbState != scan['state']) {
var usbResult = await _rpc.command('get', ['usb']); var usbResult = await _rpc.command('get', ['usb']);
developer.log('USB state change', log.info('USB state change', jsonEncode(usbResult));
name: 'controller', error: jsonEncode(usbResult));
_usbState = usbResult['data']['state']; _usbState = usbResult['data']['state'];

View File

@ -1,12 +1,14 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:developer' as developer;
import 'package:logging/logging.dart';
import 'package:async/async.dart'; import 'package:async/async.dart';
import 'models.dart'; import 'models.dart';
final log = Logger('rpc');
class Signaler { class Signaler {
final _send = StreamController<String>(); final _send = StreamController<String>();
final _recv = StreamController<Signal>(); final _recv = StreamController<Signal>();
@ -40,6 +42,21 @@ class _Request {
}; };
} }
Level _forPythonName(String name) {
switch (name) {
case 'DEBUG':
return Level.CONFIG;
case 'INFO':
return Level.INFO;
case 'WARNING':
return Level.WARNING;
case 'ERROR':
return Level.SEVERE;
default:
return Level.INFO;
}
}
class RpcSession { class RpcSession {
final Process _process; final Process _process;
final StreamController<_Request> _requests = StreamController(); final StreamController<_Request> _requests = StreamController();
@ -50,8 +67,18 @@ class RpcSession {
.transform(const Utf8Decoder()) .transform(const Utf8Decoder())
.transform(const LineSplitter()) .transform(const LineSplitter())
.map((event) => RpcResponse.fromJson(jsonDecode(event)))) { .map((event) => RpcResponse.fromJson(jsonDecode(event)))) {
stderr.addStream(_process.stderr); _process.stderr
developer.log('Launched ykman subprocess...', name: 'rpc'); .transform(const Utf8Decoder())
.transform(const LineSplitter())
.map((event) => jsonDecode(event))
.listen((event) {
Logger('rpc.${event['name']}').log(
_forPythonName(event['level']),
event['message'],
//time: DateTime.fromMillisecondsSinceEpoch(event['time'] * 1000),
);
});
log.info('Launched ykman subprocess...');
_pump(); _pump();
} }
@ -68,8 +95,24 @@ class RpcSession {
return request.completer.future; return request.completer.future;
} }
setLogLevel(Level level) {
String pyLevel;
if (level.value <= Level.CONFIG.value) {
pyLevel = 'debug';
} else if (level.value <= Level.INFO.value) {
pyLevel = 'info';
} else if (level.value <= Level.WARNING.value) {
pyLevel = 'warning';
} else if (level.value <= Level.SEVERE.value) {
pyLevel = 'error';
} else {
pyLevel = 'critical';
}
command('logging', [], params: {'level': pyLevel});
}
void _send(Map data) { void _send(Map data) {
developer.log('SEND', name: 'rpc', error: jsonEncode(data)); log.fine('SEND', jsonEncode(data));
_process.stdin.writeln(jsonEncode(data)); _process.stdin.writeln(jsonEncode(data));
_process.stdin.flush(); _process.stdin.flush();
} }
@ -85,7 +128,7 @@ class RpcSession {
bool completed = false; bool completed = false;
while (!completed) { while (!completed) {
final response = await _responses.next; final response = await _responses.next;
developer.log('RECV', name: 'rpc', error: jsonEncode(response)); log.fine('RECV', jsonEncode(response));
response.map( response.map(
signal: (signal) { signal: (signal) {
request.signal?._recv.sink.add(signal); request.signal?._recv.sink.add(signal);

View File

@ -1,10 +1,10 @@
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart';
import 'dart:developer' as developer; import 'dart:developer' as developer;
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:logging/logging.dart';
import 'app.dart'; import 'app.dart';
import 'core/rpc.dart'; import 'core/rpc.dart';
@ -13,6 +13,8 @@ import 'core/state.dart';
import 'app/main_page.dart'; import 'app/main_page.dart';
import 'error_page.dart'; import 'error_page.dart';
final log = Logger('main');
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
@ -35,14 +37,16 @@ void main() async {
prefProvider.overrideWithValue(await SharedPreferences.getInstance()) prefProvider.overrideWithValue(await SharedPreferences.getInstance())
]; ];
developer.log('Starting subprocess: $exe', name: 'main'); log.info('Starting subprocess: $exe');
try { try {
var rpc = await RpcSession.launch(exe!); var rpc = await RpcSession.launch(exe!);
developer.log('ykman process started', name: 'main'); // Enable logging TODO: Make this configurable
_initLogging(Level.INFO, rpc);
log.info('ykman process started', exe);
overrides.add(rpcProvider.overrideWithValue(rpc)); overrides.add(rpcProvider.overrideWithValue(rpc));
page = const MainPage(); page = const MainPage();
} catch (e) { } catch (e) {
developer.log('ykman process failed: $e', name: 'main'); log.warning('ykman process failed: $e');
page = ErrorPage(error: e.toString()); page = ErrorPage(error: e.toString());
} }
@ -52,6 +56,22 @@ void main() async {
)); ));
} }
void _initLogging(Level level, RpcSession rpc) {
//TODO: Add support for logging to stderr and file
Logger.root.onRecord.listen((record) {
developer.log(
'${record.level} ${record.message}',
error: record.error,
name: record.loggerName,
time: record.time,
level: record.level.value,
);
});
Logger.root.level = level;
rpc.setLogLevel(level);
}
//TODO: Remove below this //TODO: Remove below this
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {

View File

@ -1,15 +1,17 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:developer' as developer;
import 'dart:math'; import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:logging/logging.dart';
import '../core/state.dart'; import '../core/state.dart';
import 'models.dart'; import 'models.dart';
final log = Logger('oath.state');
final _sessionProvider = final _sessionProvider =
Provider.autoDispose.family<RpcNodeSession, List<String>>( Provider.autoDispose.family<RpcNodeSession, List<String>>(
(ref, devicePath) => RpcNodeSession( (ref, devicePath) => RpcNodeSession(
@ -34,8 +36,7 @@ class OathStateNotifier extends StateNotifier<OathState?> {
refresh() async { refresh() async {
var result = await _session.command('get'); var result = await _session.command('get');
developer.log('application status', log.config('application status', jsonEncode(result));
name: 'oath', error: jsonEncode(result));
if (mounted) { if (mounted) {
state = OathState.fromJson(result['data']); state = OathState.fromJson(result['data']);
} }
@ -47,7 +48,7 @@ class OathStateNotifier extends StateNotifier<OathState?> {
var key = result['key']; var key = result['key'];
await _session.command('validate', params: {'key': key}); await _session.command('validate', params: {'key': key});
if (mounted) { if (mounted) {
developer.log('UNLOCKED'); log.config('applet unlocked');
state = state?.copyWith(locked: false); state = state?.copyWith(locked: false);
} }
return true; return true;
@ -117,7 +118,7 @@ class CredentialListNotifier extends StateNotifier<List<OathPair>?> {
await _session.command('code', target: ['accounts', credential.id]); await _session.command('code', target: ['accounts', credential.id]);
code = OathCode.fromJson(result); code = OathCode.fromJson(result);
} }
developer.log('Calculate', name: 'oath', error: jsonEncode(code)); log.config('Calculate', jsonEncode(code));
if (mounted) { if (mounted) {
final creds = state!.toList(); final creds = state!.toList();
final i = creds.indexWhere((e) => e.credential.id == credential.id); final i = creds.indexWhere((e) => e.credential.id == credential.id);
@ -143,9 +144,9 @@ class CredentialListNotifier extends StateNotifier<List<OathPair>?> {
refresh() async { refresh() async {
if (_locked) return; if (_locked) return;
developer.log('refreshing credentials...', name: 'oath'); log.config('refreshing credentials...');
var result = await _session.command('calculate_all', target: ['accounts']); var result = await _session.command('calculate_all', target: ['accounts']);
developer.log('Entries', name: 'oath', error: jsonEncode(result)); log.config('Entries', jsonEncode(result));
if (mounted) { if (mounted) {
var current = state?.toList() ?? []; var current = state?.toList() ?? [];

View File

@ -304,7 +304,7 @@ packages:
source: hosted source: hosted
version: "1.0.1" version: "1.0.1"
logging: logging:
dependency: transitive dependency: "direct main"
description: description:
name: logging name: logging
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"

View File

@ -36,6 +36,7 @@ dependencies:
# cupertino_icons: ^1.0.2 # cupertino_icons: ^1.0.2
async: ^2.8.2 async: ^2.8.2
logging: ^1.0.2
shared_preferences: ^2.0.8 shared_preferences: ^2.0.8
flutter_riverpod: ^1.0.0 flutter_riverpod: ^1.0.0
json_annotation: ^4.3.0 json_annotation: ^4.3.0

@ -1 +1 @@
Subproject commit 739f3122a43adfcd2549374bc4cd11e88a483a8d Subproject commit 318b0981d545950a45a8c9b9e17de9332e1f64b5