Added default logging
This commit is contained in:
parent
6d2be10536
commit
ff65e13c75
12 changed files with 85 additions and 144 deletions
|
@ -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`
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -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 = [];
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io' show BytesBuilder;
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:angel3_container/mirrors.dart';
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in a new issue