Added default logging

This commit is contained in:
thomashii 2022-02-20 09:48:12 +08:00
parent 6d2be10536
commit ff65e13c75
12 changed files with 85 additions and 144 deletions

View file

@ -1,5 +1,17 @@
# Change Log
## 6.0.0
* Updated to min SDK 2.15.x
## 5.0.0
* Skipped release
## 4.0.0
* Skipped release
## 3.0.1
* Updated `package:angel3_container`

View file

@ -1,6 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io' show stderr, Cookie;
import 'dart:io' show Cookie;
import 'package:angel3_http_exception/angel3_http_exception.dart';
import 'package:angel3_route/angel3_route.dart';
import 'package:belatuk_combinator/belatuk_combinator.dart';
@ -20,10 +20,6 @@ abstract class Driver<
final Angel app;
final bool useZone;
bool _closed = false;
late Server _server;
// TODO: Ugly fix
bool isServerInitialised = false;
StreamSubscription<Request>? _sub;
//final log = Logger('Driver');
@ -37,14 +33,7 @@ abstract class Driver<
Uri get uri;
/// The native server running this instance.
Server? get server {
// TODO: Ugly fix
if (isServerInitialised) {
return _server;
} else {
return null;
}
}
Server? server;
Future<Server> generateServer(address, int port) =>
serverGenerator(address, port);
@ -53,24 +42,21 @@ abstract class Driver<
Future<Server> startServer([address, int port = 0]) {
var host = address ?? '127.0.0.1';
return generateServer(host, port).then((server) {
_server = server;
// TODO: Ugly fix
isServerInitialised = true;
this.server = server;
return Future.wait(app.startupHooks.map(app.configure)).then((_) {
app.optimizeForProduction();
_sub = server.listen((request) {
_sub = this.server?.listen((request) {
var stream = createResponseStreamFromRawRequest(request);
stream.listen((response) {
// TODO: To be revisited
handleRawRequest(request, response);
});
});
return Future.value(_server);
return Future.value(this.server!);
});
}).catchError((error) {
app.logger?.severe('Failed to create server', error);
app.logger.severe('Failed to create server', error);
throw ArgumentError('[Driver]Failed to create server');
});
}
@ -163,7 +149,7 @@ abstract class Driver<
..registerSingleton<ParseResult<RouteResult>?>(tuple.item3)
..registerSingleton<ParseResult?>(tuple.item3);
if (!app.environment.isProduction && app.logger != null) {
if (!app.environment.isProduction) {
req.container?.registerSingleton<Stopwatch>(Stopwatch()..start());
}
@ -204,22 +190,16 @@ abstract class Driver<
message: ee?.toString() ?? '500 Internal Server Error');
}
if (app.logger != null) {
var error = e.error ?? e;
var trace = Trace.from(StackTrace.current).terse;
app.logger?.severe(e.message, error, trace);
}
app.logger.severe(e.message, error, trace);
return handleAngelHttpException(e, st, req, res, request, response);
});
} else {
var zoneSpec = ZoneSpecification(
print: (self, parent, zone, line) {
if (app.logger != null) {
app.logger?.info(line);
} else {
parent.print(zone, line);
}
app.logger.info(line);
},
handleUncaughtError: (self, parent, zone, error, stackTrace) {
var trace = Trace.from(stackTrace).terse;
@ -237,9 +217,7 @@ abstract class Driver<
stackTrace: stackTrace, message: error.toString());
}
if (app.logger != null) {
app.logger?.severe(e.message, error, trace);
}
app.logger.severe(e.message, error, trace);
return handleAngelHttpException(
e, trace, req, res, request, response);
@ -248,23 +226,15 @@ abstract class Driver<
closeResponse(response);
// Ideally, we won't be in a position where an absolutely fatal error occurs,
// but if so, we'll need to log it.
if (app.logger != null) {
app.logger!.severe(
app.logger.severe(
'Fatal error occurred when processing $uri.', e, trace);
} else {
stderr
..writeln('Fatal error occurred when processing '
'${req.uri}:')
..writeln(e)
..writeln(trace);
}
});
},
);
var zone = Zone.current.fork(specification: zoneSpec);
req.container!.registerSingleton<Zone>(zone);
req.container!.registerSingleton<ZoneSpecification>(zoneSpec);
req.container?.registerSingleton<Zone>(zone);
req.container?.registerSingleton<ZoneSpecification>(zoneSpec);
// If a synchronous error is thrown, it's not caught by `zone.run`,
// so use a try/catch, and recover when need be.
@ -291,12 +261,12 @@ abstract class Driver<
{bool ignoreFinalizers = false}) {
if (req == null || res == null) {
try {
app.logger?.severe('500 Internal Server Error', e, st);
app.logger.severe('500 Internal Server Error', e, st);
setStatusCode(response, 500);
writeStringToResponse(response, '500 Internal Server Error');
closeResponse(response);
} catch (e) {
app.logger?.severe('500 Internal Server Error', e);
app.logger.severe('500 Internal Server Error', e);
}
return Future.value();
}
@ -322,11 +292,9 @@ abstract class Driver<
ResponseContext res,
{bool ignoreFinalizers = false}) {
Future<void> _cleanup(_) {
if (!app.environment.isProduction &&
app.logger != null &&
req.container!.has<Stopwatch>()) {
if (!app.environment.isProduction && req.container!.has<Stopwatch>()) {
var sw = req.container!.make<Stopwatch>();
app.logger?.info(
app.logger.info(
"${res.statusCode} ${req.method} ${req.uri} (${sw.elapsedMilliseconds} ms)");
}
return req.close();

View file

@ -9,7 +9,6 @@ import 'dart:typed_data';
import 'package:angel3_route/angel3_route.dart';
import 'package:file/file.dart';
import 'package:http_parser/http_parser.dart';
import 'package:logging/logging.dart';
import 'package:mime/mime.dart';
import 'controller.dart';
@ -25,7 +24,7 @@ abstract class ResponseContext<RawResponse>
final CaseInsensitiveMap<String> _headers = CaseInsensitiveMap<String>.from(
{'content-type': 'text/plain', 'server': 'Angel3'});
final log = Logger('ResponseContext');
//final log = Logger('ResponseContext');
Completer? _done;
int _statusCode = 200;
@ -351,7 +350,7 @@ abstract class ResponseContext<RawResponse>
if (stackTrace != null) {
Zone.current.handleUncaughtError(error, stackTrace);
} else {
log.warning('[ResponseContext] stackTrace is null');
app?.logger.warning('[ResponseContext] stackTrace is null');
}
}
}

View file

@ -46,6 +46,11 @@ RequestHandler chain(Iterable<RequestHandler> handlers) {
class Routable extends Router<RequestHandler> {
final Map<Pattern, Service> _services = {};
final Map<Pattern, Service?> _serviceLookups = {};
/// A [Map] of application-specific data that can be accessed.
///
/// Packages like `package:angel3_configuration` populate this map
/// for you.
final Map configuration = {};
final Container _container;

View file

@ -55,6 +55,18 @@ Future<bool> _defaultErrorHandler(
}
}
Logger _defaultLogger() {
Logger logger = Logger('SERVER')
//..level = Level.WARNING
..onRecord.listen((rec) {
print(rec);
if (rec.error != null) print(rec.error);
if (rec.stackTrace != null) print(rec.stackTrace);
});
return logger;
}
/// A powerful real-time/REST/MVC server class.
class Angel extends Routable {
static Future<String> _noViewEngineConfigured(String view, [Map? data]) =>
@ -99,19 +111,6 @@ class Angel extends Routable {
/// A set of [Controller] objects that have been loaded into the application.
Map<Pattern, Controller> get controllers => _controllers;
/// Now *deprecated*, in favor of [AngelEnv] and [angelEnv]. Use `app.environment.isProduction`
/// instead.
///
/// Indicates whether the application is running in a production environment.
///
/// The criteria for this is the `ANGEL_ENV` environment variable being set to
/// `'production'`.
///
/// This value is memoized the first time you call it, so do not change environment
/// configuration at runtime!
//@deprecated
//bool get isProduction => environment.isProduction;
/// The [AngelEnvironment] in which the application is running.
///
/// By default, it is automatically inferred.
@ -121,7 +120,7 @@ class Angel extends Routable {
Angel? get parent => _parent;
/// Outputs diagnostics and debug messages.
Logger? logger;
Logger logger = _defaultLogger();
/// Plug-ins to be called right before server startup.
///
@ -138,14 +137,6 @@ class Angel extends Routable {
/// These will only not run if a response's `willCloseItself` is set to `true`.
final List<RequestHandler> responseFinalizers = [];
/// A [Map] of application-specific data that can be accessed by any
/// piece of code that can see this [Angel] instance.
///
/// Packages like `package:angel3_configuration` populate this map
/// for you.
@override
final Map configuration = {};
/// A function that renders views.
///
/// Called by [ResponseContext]@`render`.
@ -158,11 +149,10 @@ class Angel extends Routable {
Route<RequestHandler> addRoute(
String method, String path, RequestHandler handler,
{Iterable<RequestHandler> middleware = const []}) {
//middleware ??= [];
if (_flattened != null) {
logger?.warning(
logger.warning(
'WARNING: You added a route ($method $path) to the router, after it had been optimized.');
logger?.warning(
logger.warning(
'This route will be ignored, and no requests will ever reach it.');
}
@ -173,9 +163,9 @@ class Angel extends Routable {
SymlinkRoute<RequestHandler> mount(
String path, Router<RequestHandler> router) {
if (_flattened != null) {
logger?.warning(
logger.warning(
'WARNING: You added mounted a child router ($path) on the router, after it had been optimized.');
logger?.warning(
logger.warning(
'This route will be ignored, and no requests will ever reach it.');
}
@ -202,7 +192,7 @@ class Angel extends Routable {
///
/// The server will be **COMPLETELY DEFUNCT** after this operation!
@override
Future close() {
Future<void> close() {
Future.forEach(services.values, (Service service) {
service.close();
});
@ -212,14 +202,13 @@ class Angel extends Routable {
_preContained.clear();
handlerCache.clear();
encoders.clear();
//_serializer = json.encode;
_children.clear();
_parent = null;
logger = null;
//_parent = null;
//logger = null;
//_flattened = null;
startupHooks.clear();
shutdownHooks.clear();
responseFinalizers.clear();
_flattened = null;
return Future.value();
}
@ -312,7 +301,7 @@ class Angel extends Routable {
void optimizeForProduction({bool force = false}) {
if (environment.isProduction || force == true) {
_flattened ??= flatten(this);
logger?.info('Angel is running in production mode.');
logger.info('Angel is running in production mode.');
}
}
@ -391,16 +380,21 @@ class Angel extends Routable {
{Reflector reflector =
const ThrowingReflector(errorMessage: _reflectionErrorMessage),
this.environment = angelEnv,
this.logger,
Logger? logger,
this.allowMethodOverrides = true,
this.serializer,
this.viewGenerator})
: super(reflector) {
// Override default logger
if (logger != null) {
this.logger = logger;
}
if (reflector is EmptyReflector || reflector is ThrowingReflector) {
var msg =
'No `reflector` was passed to the Angel constructor, so reflection will not be available.\n' +
_reflectionInfo;
logger?.warning(msg);
this.logger.warning(msg);
}
bootstrapContainer();

View file

@ -103,15 +103,10 @@ class AngelHttp extends Driver<HttpRequest, HttpResponse, HttpServer,
Future<HttpResponseContext> createResponseContext(
HttpRequest request, HttpResponse response,
[HttpRequestContext? correspondingRequest]) {
// TODO: Refactored to overcome NNBD migration error
var context = HttpResponseContext(response, app, correspondingRequest);
context.serializer = (app.serializer ?? json.encode);
context.encoders.addAll(app.encoders);
return Future<HttpResponseContext>.value(context);
// return Future<HttpResponseContext>.value(
// HttpResponseContext(response, app, correspondingRequest)
// ..serializer = (app.serializer ?? json.encode)
// ..encoders.addAll(app.encoders ?? {}));
}
@override

View file

@ -24,7 +24,7 @@ class HttpRequestContext extends RequestContext<HttpRequest?> {
@override
List<Cookie> get cookies {
return rawRequest!.cookies;
return rawRequest?.cookies ?? [];
}
@override
@ -51,7 +51,7 @@ class HttpRequestContext extends RequestContext<HttpRequest?> {
@override
String get originalMethod {
return rawRequest!.method;
return rawRequest?.method ?? '';
}
@override
@ -61,17 +61,18 @@ class HttpRequestContext extends RequestContext<HttpRequest?> {
@override
InternetAddress get remoteAddress {
return rawRequest!.connectionInfo!.remoteAddress;
return rawRequest?.connectionInfo?.remoteAddress ??
InternetAddress("127.0.0.1");
}
@override
HttpSession get session {
return rawRequest!.session;
HttpSession? get session {
return rawRequest?.session;
}
@override
Uri get uri {
return rawRequest!.uri;
return rawRequest?.uri ?? Uri();
}
/// Magically transforms an [HttpRequest] into a [RequestContext].
@ -92,35 +93,6 @@ class HttpRequestContext extends RequestContext<HttpRequest?> {
? MediaType('text', 'plain')
: MediaType.parse(request.headers.contentType.toString());
ctx._override = override;
/*
// Faster way to get path
List<int> _path = [];
// Go up until we reach a ?
for (int ch in request.uri.toString().codeUnits) {
if (ch != $question)
_path.add(ch);
else
break;
}
// Remove trailing slashes
int lastSlash = -1;
for (int i = _path.length - 1; i >= 0; i--) {
if (_path[i] == $slash)
lastSlash = i;
else
break;
}
if (lastSlash > -1)
ctx._path = String.fromCharCodes(_path.take(lastSlash));
else
ctx._path = String.fromCharCodes(_path);
*/
ctx._path = path;
ctx._io = request;

View file

@ -13,15 +13,15 @@ class HttpResponseContext extends ResponseContext<HttpResponse> {
@override
final HttpResponse rawResponse;
@override
Angel? app;
LockableBytesBuilder? _buffer;
final HttpRequestContext? _correspondingRequest;
bool _isDetached = false, _isClosed = false, _streamInitialized = false;
HttpResponseContext(this.rawResponse, this.app, [this._correspondingRequest]);
HttpResponseContext(this.rawResponse, Angel? app,
[this._correspondingRequest]) {
this.app = app;
}
@override
HttpResponse detach() {

View file

@ -80,7 +80,7 @@ class AngelHttp2 extends Driver<Socket, ServerTransportStream,
@override
Future<void> close() async {
await _artificial!.close();
await _artificial?.close();
await _http.close();
return await super.close();
}
@ -211,7 +211,7 @@ class _AngelHttp2ServerSocket extends Stream<SecureSocket>
},
onDone: _ctrl.close,
onError: (e, st) {
driver.app.logger!.warning(
driver.app.logger.warning(
'HTTP/2 incoming connection failure: ', e, st as StackTrace);
},
);

View file

@ -6,9 +6,6 @@ import 'package:http2/transport.dart';
import 'http2_request_context.dart';
class Http2ResponseContext extends ResponseContext<ServerTransportStream> {
@override
final Angel? app;
final ServerTransportStream stream;
@override
@ -25,8 +22,9 @@ class Http2ResponseContext extends ResponseContext<ServerTransportStream> {
Uri? _targetUri;
Http2ResponseContext(this.app, this.stream, this._req) {
_targetUri = _req!.uri;
Http2ResponseContext(Angel? app, this.stream, this._req) {
this.app = app;
_targetUri = _req?.uri;
}
final List<Http2ResponseContext> _pushes = [];

View file

@ -1,6 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io' show BytesBuilder;
import 'dart:io';
import 'package:angel3_container/mirrors.dart';

View file

@ -1,6 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io' show stderr;
import 'dart:io';
import 'package:angel3_container/mirrors.dart';
@ -92,7 +91,7 @@ void main() {
test('cannot write after close', () async {
try {
var rq = MockHttpRequest('GET', Uri.parse('/overwrite'));
await (rq.close());
await rq.close();
await http.handleRequest(rq);
var body = await rq.response.transform(utf8.decoder).join();