dart-backend / angel

A polished, production-ready backend framework in Dart for the VM, AOT, and Flutter.
https://github.com/dukefirehawk/angel
BSD 3-Clause "New" or "Revised" License
171 stars 22 forks source link

===== CRASH ===== si_signo=Segmentation fault(11), si_code=128, si_addr=(nil) version=2.18.7 (stable) (Unknown timestamp) on "linux_x64" pid=2718, thread=2870, isolate_group=main(0x55f5de84b800), isolate=(nil)((nil)) #113

Open insinfo opened 7 months ago

insinfo commented 7 months ago

I'm getting this error in my application with Angel 7.0.0 and dart 2.18.7 on Debian 11 with libc 2.31

the error is intermittent, in the tests I did when I run wrk for the fifth time the error appears and angel restarts

/wrk -t12 -c400 -d30s http://localhost:3150

error in AOT mode

 ../../runtime/vm/raw_object.cc: 356: error: Invalid cid: 0, obj: 0x7f78b60e0b68, tags: 2c. Corrupt heap?

error in JIT mode

===== CRASH =====
si_signo=Segmentation fault(11), si_code=128, si_addr=(nil)
version=2.18.7 (stable) (Unknown timestamp) on "linux_x64"
pid=2718, thread=2870, isolate_group=main(0x55f5de84b800), isolate=(nil)((nil))
isolate_instructions=55f5dd0fd680, vm_instructions=55f5dd0fd680
  pc 0x000055f5dd42028b fp 0x00007f0eef27c3a0 dart+0x222628b
  pc 0x000055f5dd420ff0 fp 0x00007f0eef27c3d0 dart+0x2226ff0
  pc 0x000055f5dd41fe50 fp 0x00007f0eef27c4f0 dart+0x2225e50
  pc 0x000055f5dd41ec29 fp 0x00007f0eef27c570 dart+0x2224c29
  pc 0x000055f5dd41e27c fp 0x00007f0eef27c640 dart::Scavenger::ParallelScavenge(dart::SemiSpace*)+0x25c
  pc 0x000055f5dd41db6c fp 0x00007f0eef27c710 dart::Scavenger::Scavenge(dart::Thread*, dart::GCType, dart::GCReason)+0x1bc
  pc 0x000055f5dd40cac3 fp 0x00007f0eef27c800 dart::Heap::CollectNewSpaceGarbage(dart::Thread*, dart::GCType, dart::GCReason)+0x103
  pc 0x000055f5dd40c067 fp 0x00007f0eef27c830 dart::Heap::AllocateNew(dart::Thread*, long)+0x107
  pc 0x000055f5dd2ecdef fp 0x00007f0eef27c880 dart::Object::Allocate(long, long, dart::Heap::Space, bool)+0x6f
  pc 0x000055f5dd3b0882 fp 0x00007f0eef27cdf0 dart::DRT_AllocateObject(dart::NativeArguments)+0x132
  pc 0x00007f0f1be025c3 fp 0x00007f0eef27ce38 Unknown symbol
  pc 0x00007f0f1be02348 fp 0x00007f0eef27ce70 Unknown symbol
  pc 0x00007f0eee8065be fp 0x00007f0eef27ced8 Unknown symbol
  pc 0x00007f0eee87f99b fp 0x00007f0eef27cf28 Unknown symbol
  pc 0x00007f0f09fd3c5d fp 0x00007f0eef27cfb0 Unknown symbol
  pc 0x00007f0f09fd2a24 fp 0x00007f0eef27d070 Unknown symbol
  pc 0x00007f0eee87f95d fp 0x00007f0eef27d0c0 Unknown symbol
  pc 0x00007f0eee87a131 fp 0x00007f0eef27d138 Unknown symbol
  pc 0x00007f0eee87f97c fp 0x00007f0eef27d188 Unknown symbol
  pc 0x00007f0eee847a04 fp 0x00007f0eef27d200 Unknown symbol
  pc 0x00007f0eee87f93e fp 0x00007f0eef27d250 Unknown symbol
  pc 0x00007f0f11b01441 fp 0x00007f0eef27d310 Unknown symbol
  pc 0x00007f0eee87f9f8 fp 0x00007f0eef27d360 Unknown symbol
  pc 0x00007f0f11b0f1b8 fp 0x00007f0eef27d3a8 Unknown symbol
  pc 0x00007f0eee87fa3b fp 0x00007f0eef27d3f8 Unknown symbol
  pc 0x00007f0f09fd2994 fp 0x00007f0eef27d4b8 Unknown symbol
  pc 0x00007f0eee87f95d fp 0x00007f0eef27d508 Unknown symbol
  pc 0x00007f0eee80659d fp 0x00007f0eef27d580 Unknown symbol
  pc 0x00007f0eee87f99b fp 0x00007f0eef27d5d0 Unknown symbol
  pc 0x00007f0eee80659d fp 0x00007f0eef27d648 Unknown symbol
  pc 0x00007f0eee87f99b fp 0x00007f0eef27d698 Unknown symbol
  pc 0x00007f0f09fd29b0 fp 0x00007f0eef27d758 Unknown symbol
  pc 0x00007f0eee87f95d fp 0x00007f0eef27d7a8 Unknown symbol
  pc 0x00007f0eee87a131 fp 0x00007f0eef27d820 Unknown symbol
  pc 0x00007f0eee87f97c fp 0x00007f0eef27d870 Unknown symbol
  pc 0x00007f0f11b095ec fp 0x00007f0eef27d8b8 Unknown symbol
  pc 0x00007f0eee87fa3b fp 0x00007f0eef27d908 Unknown symbol
  pc 0x00007f0eee847a04 fp 0x00007f0eef27d980 Unknown symbol
  pc 0x00007f0eee87f93e fp 0x00007f0eef27d9d0 Unknown symbol
  pc 0x00007f0f11b05c53 fp 0x00007f0eef27da28 Unknown symbol
  pc 0x00007f0f11b02cfd fp 0x00007f0eef27da88 Unknown symbol
  pc 0x00007f0f11b0fc14 fp 0x00007f0eef27dad8 Unknown symbol
  pc 0x00007f0f11b0aaac fp 0x00007f0eef27db38 Unknown symbol
  pc 0x00007f0f11b11884 fp 0x00007f0eef27dba0 Unknown symbol
  pc 0x00007f0eee81b7c2 fp 0x00007f0eef27dc18 Unknown symbol
  pc 0x00007f0f11b117e4 fp 0x00007f0eef27dc68 Unknown symbol
  pc 0x00007f0eee81b7c2 fp 0x00007f0eef27dce0 Unknown symbol
  pc 0x00007f0f09fe0609 fp 0x00007f0eef27dd88 Unknown symbol
  pc 0x00007f0f08a2b32f fp 0x00007f0eef27dde8 Unknown symbol
  pc 0x00007f0f08a29cce fp 0x00007f0eef27de78 Unknown symbol
  pc 0x00007f0f09fee3a8 fp 0x00007f0eef27def0 Unknown symbol
  pc 0x00007f0f09feca6c fp 0x00007f0eef27df60 Unknown symbol
  pc 0x00007f0f08a23609 fp 0x00007f0eef27e010 Unknown symbol
  pc 0x00007f0ee36ffd0f fp 0x00007f0eef27e0a0 Unknown symbol
  pc 0x00007f0ef0d7f5ce fp 0x00007f0eef27e0f8 Unknown symbol
  pc 0x00007f0eee84857c fp 0x00007f0eef27e188 Unknown symbol
  pc 0x00007f0eee81bbf6 fp 0x00007f0eef27e200 Unknown symbol
  pc 0x00007f0f08a2029b fp 0x00007f0eef27e268 Unknown symbol
  pc 0x00007f0f09fe1f91 fp 0x00007f0eef27e2b8 Unknown symbol
  pc 0x00007f0f11b16dcd fp 0x00007f0eef27e340 Unknown symbol
  pc 0x00007f0eee83f1cb fp 0x00007f0eef27e390 Unknown symbol
  pc 0x00007f0f11b19099 fp 0x00007f0eef27e418 Unknown symbol
  pc 0x00007f0f08a1f936 fp 0x00007f0eef27e480 Unknown symbol
  pc 0x00007f0eee852883 fp 0x00007f0eef27e4a8 Unknown symbol
  pc 0x00007f0f09fef8a0 fp 0x00007f0eef27e4e8 Unknown symbol
  pc 0x00007f0f1be02a0c fp 0x00007f0eef27e560 Unknown symbol
  pc 0x000055f5dd27583d fp 0x00007f0eef27e600 dart::DartEntry::InvokeCode(dart::Code const&, unsigned long, dart::Array const&, dart::Array const&, dart::Thread*)+0x14d
  pc 0x000055f5dd27567c fp 0x00007f0eef27e660 dart::DartEntry::InvokeFunction(dart::Function const&, dart::Array const&, dart::Array const&, unsigned long)+0x14c
  pc 0x000055f5dd277aac fp 0x00007f0eef27e6b0 dart::DartLibraryCalls::HandleMessage(long, dart::Instance const&)+0x14c
  pc 0x000055f5dd29f170 fp 0x00007f0eef27ec40 dart::IsolateMessageHandler::HandleMessage(std::__2::unique_ptr<dart::Message, std::__2::default_delete<dart::Message> >)+0x350
  pc 0x000055f5dd2c869d fp 0x00007f0eef27ecb0 dart::MessageHandler::HandleMessages(dart::MonitorLocker*, bool, bool)+0x14d
  pc 0x000055f5dd2c8d7f fp 0x00007f0eef27ed00 dart::MessageHandler::TaskCallback()+0x1df
  pc 0x000055f5dd3eb7b8 fp 0x00007f0eef27ed80 dart::ThreadPool::WorkerLoop(dart::ThreadPool::Worker*)+0x148
  pc 0x000055f5dd3ebc0d fp 0x00007f0eef27edb0 dart::ThreadPool::Worker::Main(unsigned long)+0x6d
  pc 0x000055f5dd35e858 fp 0x00007f0eef27ee70 dart+0x2164858
-- End of DumpStackTrace
  pc 0x0000000000000000 fp 0x00007f0eef27ce38 sp 0x0000000000000000 [Stub] CallToRuntime
  pc 0x00007f0f1be02348 fp 0x00007f0eef27ce70 sp 0x00007f0eef27ce48 [Stub] CallToRuntime
  pc 0x00007f0eee8065be fp 0x00007f0eef27ced8 sp 0x00007f0eef27ce80 [Optimized] _Map@442271956.__parse@442271956
  pc 0x00007f0eee87f99b fp 0x00007f0eef27cf28 sp 0x00007f0eef27cee8 [Optimized] Parser._parse@442271956
  pc 0x00007f0f09fd3c5d fp 0x00007f0eef27cfb0 sp 0x00007f0eef27cf38 [Optimized] _Any@442271956._parse@442271956
  pc 0x00007f0f09fd2a24 fp 0x00007f0eef27d070 sp 0x00007f0eef27cfc0 [Optimized] _Chain@442271956.__parse@442271956
  pc 0x00007f0eee87f95d fp 0x00007f0eef27d0c0 sp 0x00007f0eef27d080 [Optimized] Parser._parse@442271956
  pc 0x00007f0eee87a131 fp 0x00007f0eef27d138 sp 0x00007f0eef27d0d0 [Optimized] _Index@442271956.__parse@442271956
  pc 0x00007f0eee87f97c fp 0x00007f0eef27d188 sp 0x00007f0eef27d148 [Optimized] Parser._parse@442271956
  pc 0x00007f0eee847a04 fp 0x00007f0eef27d200 sp 0x00007f0eef27d198 [Optimized] _Cast@442271956.__parse@442271956
  pc 0x00007f0eee87f93e fp 0x00007f0eef27d250 sp 0x00007f0eef27d210 [Optimized] Parser._parse@442271956
  pc 0x00007f0f11b01441 fp 0x00007f0eef27d310 sp 0x00007f0eef27d260 [Optimized] _Repeat@442271956.__parse@442271956
  pc 0x00007f0eee87f9f8 fp 0x00007f0eef27d360 sp 0x00007f0eef27d320 [Optimized] Parser._parse@442271956
  pc 0x00007f0f11b0f1b8 fp 0x00007f0eef27d3a8 sp 0x00007f0eef27d370 [Optimized] _ListOpt@442271956.__parse@442271956
  pc 0x00007f0eee87fa3b fp 0x00007f0eef27d3f8 sp 0x00007f0eef27d3b8 [Optimized] Parser._parse@442271956
  pc 0x00007f0f09fd2994 fp 0x00007f0eef27d4b8 sp 0x00007f0eef27d408 [Optimized] _Chain@442271956.__parse@442271956
  pc 0x00007f0eee87f95d fp 0x00007f0eef27d508 sp 0x00007f0eef27d4c8 [Optimized] Parser._parse@442271956
  pc 0x00007f0eee80659d fp 0x00007f0eef27d580 sp 0x00007f0eef27d518 [Optimized] _Map@442271956.__parse@442271956
  pc 0x00007f0eee87f99b fp 0x00007f0eef27d5d0 sp 0x00007f0eef27d590 [Optimized] Parser._parse@442271956
  pc 0x00007f0eee80659d fp 0x00007f0eef27d648 sp 0x00007f0eef27d5e0 [Optimized] _Map@442271956.__parse@442271956
  pc 0x00007f0eee87f99b fp 0x00007f0eef27d698 sp 0x00007f0eef27d658 [Optimized] Parser._parse@442271956
  pc 0x00007f0f09fd29b0 fp 0x00007f0eef27d758 sp 0x00007f0eef27d6a8 [Optimized] _Chain@442271956.__parse@442271956
  pc 0x00007f0eee87f95d fp 0x00007f0eef27d7a8 sp 0x00007f0eef27d768 [Optimized] Parser._parse@442271956
  pc 0x00007f0eee87a131 fp 0x00007f0eef27d820 sp 0x00007f0eef27d7b8 [Optimized] _Index@442271956.__parse@442271956
  pc 0x00007f0eee87f97c fp 0x00007f0eef27d870 sp 0x00007f0eef27d830 [Optimized] Parser._parse@442271956
  pc 0x00007f0f11b095ec fp 0x00007f0eef27d8b8 sp 0x00007f0eef27d880 [Optimized] _CastDynamic@442271956.__parse@442271956
  pc 0x00007f0eee87fa3b fp 0x00007f0eef27d908 sp 0x00007f0eef27d8c8 [Optimized] Parser._parse@442271956
  pc 0x00007f0eee847a04 fp 0x00007f0eef27d980 sp 0x00007f0eef27d918 [Optimized] _Cast@442271956.__parse@442271956
  pc 0x00007f0eee87f93e fp 0x00007f0eef27d9d0 sp 0x00007f0eef27d990 [Optimized] Parser._parse@442271956
  pc 0x00007f0f11b05c53 fp 0x00007f0eef27da28 sp 0x00007f0eef27d9e0 [Optimized] new Route.
  pc 0x00007f0f11b02cfd fp 0x00007f0eef27da88 sp 0x00007f0eef27da38 [Optimized] new Route.join
  pc 0x00007f0f11b0fc14 fp 0x00007f0eef27dad8 sp 0x00007f0eef27da98 [Optimized] Router.get:routes.<anonymous closure>.<anonymous closure>
  pc 0x00007f0f11b0aaac fp 0x00007f0eef27db38 sp 0x00007f0eef27dae8 [Optimized] _ListBase&Object&ListMixin@3220832.fold
  pc 0x00007f0f11b11884 fp 0x00007f0eef27dba0 sp 0x00007f0eef27db48 [Optimized] Router.get:routes.<anonymous closure>
  pc 0x00007f0eee81b7c2 fp 0x00007f0eef27dc18 sp 0x00007f0eef27dbb0 [Optimized] Router.get:routes
  pc 0x00007f0f11b117e4 fp 0x00007f0eef27dc68 sp 0x00007f0eef27dc28 [Optimized] Router.get:routes.<anonymous closure>
  pc 0x00007f0eee81b7c2 fp 0x00007f0eef27dce0 sp 0x00007f0eef27dc78 [Optimized] Router.get:routes
  pc 0x00007f0f09fe0609 fp 0x00007f0eef27dd88 sp 0x00007f0eef27dcf0 [Optimized] Router.resolve.crawl
  pc 0x00007f0f08a2b32f fp 0x00007f0eef27dde8 sp 0x00007f0eef27dd98 [Optimized] Router.resolve
  pc 0x00007f0f08a29cce fp 0x00007f0eef27de78 sp 0x00007f0eef27ddf8 [Optimized] Router.resolveAll
  pc 0x00007f0f09fee3a8 fp 0x00007f0eef27def0 sp 0x00007f0eef27de88 [Optimized] Driver.handleRawRequest.<anonymous closure>.<anonymous closure>.handle.resolveTuple
  pc 0x00007f0f09feca6c fp 0x00007f0eef27df60 sp 0x00007f0eef27df00 [Optimized] Driver.handleRawRequest.<anonymous closure>.<anonymous closure>.handle
  pc 0x00007f0f08a23609 fp 0x00007f0eef27e010 sp 0x00007f0eef27df70 [Optimized] Driver.handleRawRequest.<anonymous closure>.<anonymous closure>
  pc 0x00007f0ee36ffd0f fp 0x00007f0eef27e0a0 sp 0x00007f0eef27e020 [Optimized] _rootRunUnary@4048458
  pc 0x00007f0ef0d7f5ce fp 0x00007f0eef27e0f8 sp 0x00007f0eef27e0b0 [Optimized] _rootRunUnary@4048458
  pc 0x00007f0eee84857c fp 0x00007f0eef27e188 sp 0x00007f0eef27e108 [Optimized] _FutureListener@4048458.handleValue
  pc 0x00007f0eee81bbf6 fp 0x00007f0eef27e200 sp 0x00007f0eef27e198 [Optimized] _Future@4048458._propagateToListeners@4048458.handleValueCallback
  pc 0x00007f0f08a2029b fp 0x00007f0eef27e268 sp 0x00007f0eef27e210 [Optimized] _Future@4048458._propagateToListeners@4048458
  pc 0x00007f0f09fe1f91 fp 0x00007f0eef27e2b8 sp 0x00007f0eef27e278 [Optimized] _Future@4048458._asyncCompleteWithValue@4048458.<anonymous closure>
  pc 0x00007f0f11b16dcd fp 0x00007f0eef27e340 sp 0x00007f0eef27e2c8 [Optimized] _rootRun@4048458
  pc 0x00007f0eee83f1cb fp 0x00007f0eef27e390 sp 0x00007f0eef27e350 [Optimized] _rootRun@4048458
  pc 0x00007f0f11b19099 fp 0x00007f0eef27e418 sp 0x00007f0eef27e3a0 [Optimized] _CustomZone@4048458.bindCallback.<anonymous closure>
  pc 0x00007f0f08a1f936 fp 0x00007f0eef27e480 sp 0x00007f0eef27e428 [Optimized] _startMicrotaskLoop@4048458
  pc 0x00007f0eee852883 fp 0x00007f0eef27e4a8 sp 0x00007f0eef27e490 [Optimized] _startMicrotaskLoop@4048458
  pc 0x00007f0f09fef8a0 fp 0x00007f0eef27e4e8 sp 0x00007f0eef27e4b8 [Optimized] _RawReceivePortImpl@1026248._handleMessage@1026248
  pc 0x00007f0f1be02a0c fp 0x00007f0eef27e560 sp 0x00007f0eef27e4f8 [Stub] InvokeDartCode

pubspec.yaml

name: new_sali_backend
description: Backend do Novo Sali

environment:  
  sdk: '>=2.18.0 < 3.0.0'

dependencies: 
  angel3_framework: ^7.0.0  
  angel3_auth: ^7.0.0
  angel3_configuration: any  
  angel3_jael: any
  angel3_production: any
  angel3_static: any
  angel3_validate: any
  angel3_cors: any
  belatuk_pretty_logging: any
  uuid: any
  dotenv: any
  intl: any
  http:  any
  path: any
  jaguar_jwt: any
  crypto: any
  xml: any
  csslib: any
  # para assinar PDF
  dart_pdf:
   git:
    url: https://github.com/insinfo/insinfo_dart_pdf
    ref: main    #branch name  
  asn1lib: any
  pointycastle: any
  basic_utils: any
  image: any  
  convert: any

  #eloquent: 
    #path: ../../eloquent  

  #eloquent:
   #git:
      #ref: main
      #url: https://github.com/insinfo/eloquent_dart.git     
  eloquent: ^2.1.2

  new_sali_core:
    path: ../core
  # para monitoramento com o prometheus e grafana
  prometheus_client: any  
  # shelf é usado no backend publico
  shelf: any #^1.3.0
  shelf_router: any #^1.1.2
  shelf_plus: any #1.7.0
  shelf_cors_headers: any #1.7.0 
  prometheus_client_shelf: any
  # para doc 
  shelf_swagger_ui: any
  ffi: any

dev_dependencies: 
  angel3_hot: any
  angel3_test: any
  test: any
  # para test de UI
  puppeteer: 2.23.0

wrk out

unabe to record last byte metrics 1699396277780273 - 1699396249892151 = 27888122
unabe to record last byte metrics 1699396277782380 - 1699396249889571 = 27892809
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
unable to record first byte metrics
  Thread Stats   Avg     Stdev       Max       Min   +/- Stdev
    Latency   989.96ms  286.53ms    2.00s    79.42ms   90.09%
    Req/Sec    19.00     14.04    100.00      0.00     79.32%
  5317 requests in 30.08s, 1.57MB read
  Socket errors: connect 0, read 0, write 0, timeout 382
  Non-2xx or 3xx responses: 42
Requests/sec:    176.74
Transfer/sec:     53.51KB
leonardomw commented 7 months ago

I have the same problem. :\

insinfo commented 7 months ago

I created a minimal app to reproduce the problem

I managed to reproduce the problem on my Windows 11 machine and running the app on WSL Debian 12, for the problem to occur I had to run wrk about 7 times ./wrk -t24 -c800 -d90s http://172.30.82.2: 3350image image

minimal app to reproduce the problem

import 'package:angel3_framework/angel3_framework.dart';
import 'package:angel3_production/angel3_production.dart';
import 'package:angel3_cors/angel3_cors.dart';
import 'dart:convert';
import 'package:file/file.dart' as file;
import 'package:angel3_static/angel3_static.dart' as static_file_server;
import 'dart:async';
import 'package:file/local.dart';

//to run: dart ./bin/main.dart -p 3350 -a 0.0.0.0 -j 4
main(List<String> args) async {
  return Runner('angel', configureServer).run(args);
}

Future configureServer(Angel app) async {
  final options = CorsOptions();
  app.fallback(cors(options));
  final fs = const LocalFileSystem();
  await app.configure(configureRoutes(fs));
}

AngelConfigurer configureRoutes(file.FileSystem fileSystem) {
  return (Angel app) {
    app.get('/', (req, res) => res.write('angel'));   

    // app.chain([simulatedMiddleware]).group('/api/v1', (router) {
    //   for (final sr in simulatedRoutes) {
    //     final method = sr.keys.first.toUpperCase();
    //     final path = sr.values.first;
    //     router.addRoute(method, path, (req, res) => simulatedWork);
    //   }
    // });

    for (final sr in simulatedRoutes) {
      final method = sr.keys.first.toUpperCase();
      final path = sr.values.first;
      app.addRoute(method, '/api/v1' + path, (req, res) => simulatedWork,middleware: [simulatedMiddleware]);
    }

    if (!app.environment.isProduction) {
      var vDir = static_file_server.VirtualDirectory(
        app,
        fileSystem,
        source: fileSystem.directory('storage'),
      );
      app.fallback(vDir.handleRequest);
    }

    app.fallback((req, res) {
      res.headers['Content-Type'] = 'application/json;charset=utf-8';
      res.statusCode = 404;
      return res.write(jsonEncode({
        'message': 'Rota não existe',
        'exception': 'Rota não existe',
        'stackTrace': ''
      }));
    });

    final oldErrorHandler = app.errorHandler;
    app.errorHandler = (e, req, res) async {
      if (req.accepts('text/html', strict: true)) {
        if (e.statusCode == 404 && req.accepts('text/html', strict: true)) {
          await res
              .render('error', {'message': 'Arquivo não existe ${req.uri}.'});
        } else {
          await res.render('error', {'message': e.message});
        }
      } else {
        return await oldErrorHandler(e, req, res);
      }
    };
  };
}

final simulatedRoutes = [
  {'get': '/administracao/paises'},
  {'get': '/administracao/ufs'},
  {'get': '/administracao/municipios'},
  {'get': '/administracao/modulos'},
  {'get': '/administracao/permissoes/:numCgm/:anoExercicio'},
  {'put': '/administracao/permissoes/:numCgm/:anoExercicio'},
  {'get': '/administracao/escolaridades'},
  {'get': '/administracao/tiposlogradouro'},
  {'get': '/administracao/orgaos'},
  {'get': '/administracao/unidades'},
  {'get': '/administracao/departamentos'},
  {'get': '/administracao/setores'},
  {'get': '/administracao/gestao'},
  {'get': '/administracao/usuarios'},
  {'get': '/administracao/usuarios/:numcgm'},
  {'post': '/administracao/usuarios'},
  {'put': '/administracao/usuarios'},
  {'get': '/administracao/cgm'},
  {'get': '/administracao/cgm/:cgm'},
  {'get': '/administracao/auditorias'},
  {'post': '/administracao/auditorias'},
  {'get': '/administracao/configuracao'},
  {'get': '/administracao/configuracao/by/filtro'},
  {'get': '/administracao/funcionalidades'},
  {'get': '/administracao/menu/:cgm'},
  {'get': '/administracao/organograma/hierarquia'},
  {'get': '/administracao/acoes'},
  //auth
  {'post': '/change/pass'},
  {'get': '/auth/check/permissao/:cgm'},
  {'post': '/auth/login'},
  {'post': '/auth/check'},
  {'get': '/auth/check/toke'},
  //cgm
  {'get': '/cgm/full'},
  {'get': '/cgm/full/:cgm'},
  {'delete': '/cgm'},
  {'post': '/cgm/full'},
  {'post': '/cgm/full/interno'},
  {'put': '/cgm/full'},
  {'get': '/cgm/atributos'},
  {'get': '/cgm/atributos/:cgm'},
  {'get': '/cgm/categoriashabilitacao'},
  {'get': '/cgm/tiposlogradouro'},
  //
  {'get': '/estatistica/processos/ano'},
  {'get': '/estatistica/processos/periodo/setor/primero/tramite'},
  {'get': '/estatistica/processos/situacao'},
  {'get': '/estatistica/processos/classificacao'},
  {'get': '/estatistica/processos/assunto'},
  //
  {'get': '/norma/normas'},
  //
  {'get': '/protocolo/processos/favoritos/cgm/:cgm'},
  {'post': '/protocolo/processos/favoritos'},
  {'post': '/protocolo/processos/favoritos/:codProcesso/:anoExercicio'},
  {'put': '/protocolo/processos/favoritos'},
  {'delete': '/protocolo/processos/favoritos/:id'},
  {'delete': '/protocolo/processos/favoritos/:codProcesso/:anoExercicio'},
  {'get': '/protocolo/acoes/favoritas/cgm/:cgm'},
  {'post': '/protocolo/acoes/favoritas'},
  {'post': '/protocolo/acoes/favoritas/:codAcao'},
  {'put': '/protocolo/acoes/favoritas'},
  {'delete': '/protocolo/acoes/favoritas/:id'},
  {'delete': '/protocolo/acoes/favoritas/:codAcao'},
  {'get': '/protocolo/assuntos'},
  {'post': '/protocolo/assuntos'},
  {'put': '/protocolo/assuntos'},
  {'delete': '/protocolo/assuntos'},
  {'get': '/protocolo/assuntos/:codAssunto/:codClassificacao'},
  {'get': '/protocolo/classificacoes'},
  {'post': '/protocolo/classificacoes'},
  {'put': '/protocolo/classificacoes'},
  {'delete': '/protocolo/classificacoes'},
  {'get': '/protocolo/despachospadrao'},
  {'post': '/protocolo/despachospadrao'},
  {'put': '/protocolo/despachospadrao'},
  {'delete': '/protocolo/despachospadrao'},
  {'get': '/protocolo/tramites'},
  {'post': '/protocolo/tramites'},
  {
    'put':
        '/protocolo/tramites/:codClassiOld/:codAssuntoOld/:ordemOld/:exercicioOld'
  },
  {'delete': '/protocolo/tramites'},
  {'get': '/protocolo/processos/:anoExercicio/:codProcesso'},
  {'get': '/protocolo/processos/em/apenso/:anoExercicio/:codProcesso'},
  {'get': '/protocolo/processos/apenso/a/:anoExercicio/:codProcesso'},
  {'get': '/protocolo/processos/andamentos/:anoExercicio/:codProcesso'},
  {
    'get':
        '/protocolo/processos/despachos/:anoExercicio/:codProcesso/:codAndamento/:codUsuario/:timestamp'
  },
  {'get': '/protocolo/processos'},
  {'get': '/protocolo/processos/areceber'},
  {'get': '/protocolo/processos/aemcaminhar'},
  {'get': '/protocolo/processos/byfiltros'},
  {'get': '/protocolo/processos/aapensara'},
  {'get': '/protocolo/processos/adesapensar'},
  {'get': '/protocolo/processos/adespachar'},
  {'get': '/protocolo/processos/aalterar'},
  {'get': '/protocolo/processos/acancelar'},
  {'get': '/protocolo/processos/aarquivar'},
  {'get': '/protocolo/processos/adesarquivar'},
  {'post': '/protocolo/processos'},
  {'post': '/protocolo/processos/implantar'},
  {'put': '/protocolo/processos'},
  {'post': '/protocolo/processos/receber/lote'},
  {'post': '/protocolo/processos/despachar/lote'},
  {'post': '/protocolo/processos/encaminhar/lote'},
  {'post': '/protocolo/processos/cancelarencaminhamento/lote'},
  {'post': '/protocolo/processos/apensar/lote'},
  {'post': '/protocolo/processos/desapensar/lote'},
  {'post': '/protocolo/processos/arquivar/lote'},
  {'post': '/protocolo/processos/desarquivar/lote'},
  {'post': '/protocolo/processos/anexos'},
  {'get': '/protocolo/processos/anexos/:codProcesso/:anoExercicio'},
  {'get': '/protocolo/situacoes'},
  {'get': '/protocolo/historicoarquivamento'},
  {'post': '/protocolo/historicoarquivamento'},
  {'put': '/protocolo/historicoarquivamento'},
  {'delete': '/protocolo/historicoarquivamento'},
  {'get': '/protocolo/listagemprocessos'},
  {'post': '/protocolo/listagemprocessos'},
  {'get': '/protocolo/documentos'},
  {'post': '/protocolo/documentos'},
  {'put': '/protocolo/documentos'},
  {'delete': '/protocolo/documentos'},
  {'get': '/protocolo/atributosprotocolo'},
  {'post': '/protocolo/atributosprotocolo'},
  {'put': '/protocolo/atributosprotocolo'},
  {'delete': '/protocolo/atributosprotocolo'},
  {'get': '/protocolo/processos/public/site/:anoExercicio/:codProcesso'},
];

Future<dynamic> simulatedWork(RequestContext req, ResponseContext res) async {
  try {
    // ignore: unused_local_variable
    final filters = req.queryParameters;
    final listItems = List.generate(150, (int index) => {'name': 'Jon_$index'});
    res.statusCode = 200;
    res.headers['Content-Type'] = 'application/json;charset=utf-8';
    res.headers['total-records'] = '150';
    res.write(jsonEncode(listItems));
  } catch (e, s) {
    print('simulatedWork@all $e $s');
    var v = jsonEncode({
      'is_error': true,
      'status_code': 400,
      'message': 'Error',
      'exception': e.toString(),
      'stackTrace': s.toString()
    });
    res.statusCode = 400;
    res.headers['Content-Type'] = 'application/json;charset=utf-8';
    res.write(v);
  }
}

Future<bool> simulatedMiddleware(
    RequestContext req, ResponseContext res) async {      
  try {
    //print('call simulatedMiddleware');
    return true;
  } catch (e, s) {
    print('simulatedMiddleware: $s $s');
    throw AngelHttpException.notAuthenticated(message: '$e $s');
  }
}

log

isaque@pmro174330:/mnt/c/MyDartProjects/dart_segment_fault$ dart ./bin/main.dart -p 3350 -a 0.0.0.0 -j 4

     _    _   _  ____ _____ _     _____
    / \  | \ | |/ ___| ____| |   |___ /
   / _ \ |  \| | |  _|  _| | |     |_ \
  / ___ \| |\  | |_| | |___| |___ ___) |
 /_/   \_\_| \_|\____|_____|_____|____/

A batteries-included, full-featured, full-stack framework in Dart.

https://angel3-framework.web.app

Starting `angel` application...
2023-11-08 17:59:07 INFO [angel]: No `reflector` was passed to the Angel constructor, so reflection will not be available.
Features like controllers, constructor dependency injection, and `ioc` require reflection, and will not work without it.
For more, see the documentation:
https://docs.angel-dart.dev/guides/dependency-injection#enabling-dart-mirrors-or-other-reflection
2023-11-08 17:59:07 INFO [angel]: No `reflector` was passed to the Angel constructor, so reflection will not be available.
Features like controllers, constructor dependency injection, and `ioc` require reflection, and will not work without it.
For more, see the documentation:
https://docs.angel-dart.dev/guides/dependency-injection#enabling-dart-mirrors-or-other-reflection
2023-11-08 17:59:07 INFO [angel]: No `reflector` was passed to the Angel constructor, so reflection will not be available.
Features like controllers, constructor dependency injection, and `ioc` require reflection, and will not work without it.
For more, see the documentation:
https://docs.angel-dart.dev/guides/dependency-injection#enabling-dart-mirrors-or-other-reflection
2023-11-08 17:59:07 INFO [angel]: No `reflector` was passed to the Angel constructor, so reflection will not be available.
Features like controllers, constructor dependency injection, and `ioc` require reflection, and will not work without it.
For more, see the documentation:
https://docs.angel-dart.dev/guides/dependency-injection#enabling-dart-mirrors-or-other-reflection
2023-11-08 17:59:08 INFO [angel]: Instance #1 listening at http://0.0.0.0:3350
2023-11-08 17:59:08 INFO [angel]: Instance #3 listening at http://0.0.0.0:3350
2023-11-08 17:59:08 INFO [angel]: Instance #2 listening at http://0.0.0.0:3350
2023-11-08 17:59:08 INFO [angel]: Instance #0 listening at http://0.0.0.0:3350
../../runtime/vm/raw_object.cc: 356: error: Invalid cid: 0, obj: 0x7fc3e24c2948, tags: 20. Corrupt heap?
version=2.18.7 (stable) (Unknown timestamp) on "linux_x64"
pid=155, thread=174, isolate_group=main(0x55798c1ab800), isolate=(nil)((nil))
isolate_instructions=557989298680, vm_instructions=557989298680
  pc 0x00005579894fd67c fp 0x00007fc3d937a8f0 dart::Profiler::DumpStackTrace(void*)+0x7c
  pc 0x0000557989298834 fp 0x00007fc3d937a9d0 dart::Assert::Fail(char const*, ...) const+0x84
  pc 0x000055798950e17e fp 0x00007fc3d937aa00 dart::UntaggedObject::VisitPointersPredefined(dart::ObjectPointerVisitor*, long)+0x4de
  pc 0x00005579895bb13b fp 0x00007fc3d937aa90 void dart::Scavenger::IterateStoreBuffers<true>(dart::ScavengerVisitorBase<true>*)+0xcb
  pc 0x00005579895bb00b fp 0x00007fc3d937ab10 void dart::Scavenger::IterateRoots<true>(dart::ScavengerVisitorBase<true>*)+0x16b
  pc 0x00005579895bad32 fp 0x00007fc3d937ac30 dart+0x2225d32
  pc 0x00005579895b9bef fp 0x00007fc3d937acb0 dart+0x2224bef
  pc 0x00005579895babce fp 0x00007fc3d937ace0 dart+0x2225bce
  pc 0x00005579895867b8 fp 0x00007fc3d937ad60 dart::ThreadPool::WorkerLoop(dart::ThreadPool::Worker*)+0x148
  pc 0x0000557989586c0d fp 0x00007fc3d937ad90 dart::ThreadPool::Worker::Main(unsigned long)+0x6d
  pc 0x00005579894f9858 fp 0x00007fc3d937ae50 dart+0x2164858
-- End of DumpStackTrace
Aborted
dukefirehawk commented 7 months ago

This is not really Angel3 specific issue. Angel3 is run with -j 4 which means using only 4 isolates. On the other hand wrk is run with -t12 -c400 which means 12 threads with 400 connections on each thread. There is a limit to the load that 4 isolates can deal with before being overloaded. I would suggest to try -j 100 or more to handle this kind of load. Memory and number of CPU cores also play a part in how much concurrency can get out of it.

insinfo commented 7 months ago

I did several tests here with the shelf and the problem didn't happen, and I saw that this problem only happens using the angel, and it seems to be linked to something in the router, most likely something related to the chain/group method perhaps, or the Runner

image

import 'dart:async';
import 'dart:convert';
import 'dart:isolate';
import 'package:args/args.dart';
import 'package:prometheus_client/format.dart' as format;
import 'package:prometheus_client/prometheus_client.dart';
import 'package:prometheus_client/runtime_metrics.dart' as runtime_metrics;
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:dart_segment_fault/dependencies/shelf_cors_headers_base/shelf_cors_headers_base.dart';
import 'package:dart_segment_fault/dependencies/stream_isolate/stream_isolate.dart';
// to compile
// dart compile exe -o backend.exe .\bin\backend.dart
// to test
// xargs -I % -P 8 curl "http:/192.168.66.123:3161/api/v1/protocolo/processos/public/site/2023/10" < <(printf '%s\n' {1..400})
//./wrk -t12 -c400 -d30s http://172.30.82.2:3350
// bombardier.exe  -c400 -d30s http://192.168.66.123:3350/metrics

final streamIsolates = <Map<int, BidirectionalStreamIsolate>>[];
void main(List<String> args) async {
  final parser = ArgParser()
    ..addOption('address', abbr: 'a', defaultsTo: '0.0.0.0')
    ..addOption('port', abbr: 'p', defaultsTo: '3161')
    ..addOption('isolates', abbr: 'j', defaultsTo: '3');

  final argsParsed = parser.parse(args);
  final arguments = [argsParsed['address'], int.parse(argsParsed['port'])];

  final numberOfIsolates = int.parse(argsParsed['isolates']);
  for (var i = 0; i < numberOfIsolates - 1; i++) {
    final streamIsolate = await StreamIsolate.spawnBidirectional(isolateMain,
        debugName: i.toString(), argument: [i, ...arguments]);
    streamIsolates.add({i: streamIsolate});
    streamIsolate.stream.listen((event) => receiveAndPass(event, i));
  }
}
/// receive msg from isolate and send to all isolates
void receiveAndPass(event, int idx) {
  streamIsolates.forEach((item) {
    item.values.first.send(event);
  });
}
Stream isolateMain(Stream inc, dynamic args) {
  final arguments = args as List;
  int id = arguments[0];
  String address = arguments[1];
  int port = arguments[2];
  final streamController = StreamController.broadcast();
  final reg = CollectorRegistry();
  // Register default runtime metrics
  runtime_metrics.register(reg);
  // Register http requests total
  final http_requests_total = Counter(
      name: 'http_requests_total', help: 'Total number of http api requests');
  http_requests_total.register(reg);
  // listen msg from main
  inc.listen((msg) {
    http_requests_total.inc();
  });
  _startServer([id, streamController, reg, address, port]);
  return streamController.stream;
}
void _startServer(List args) async {
  final streamController = args[1] as StreamController;
  final reg = args[2] as CollectorRegistry;
  String address = args[3];
  int port = args[4];
  final app = Router();
  routes(app, reg);
  final handler =
      Pipeline().addMiddleware(corsHeaders()).addMiddleware((innerHandler) {
    return (request) async {
      // Every time http_request is called, increase the counter by one
      final resp = await innerHandler(request);
      if (request.url.path != 'metrics') {
        //send msg to main
        streamController.add('+1');
      }
      return resp;
    };
  })
          //.addMiddleware(logRequestsCustom())
          .addHandler(app);

  final server = await io.serve(handler, address, port, shared: true);
  server.defaultResponseHeaders.remove('X-Frame-Options', 'SAMEORIGIN');
  print('Serving at http://${server.address.host}:${server.port}');
}

void routes(Router app, CollectorRegistry reg) {
  app.get('/', (Request request) async {
    return Response.ok('shelf');
  });
  // Register a handler to expose the metrics in the Prometheus text format
  app.get('/metrics', (Request request) async {
    final buffer = StringBuffer();
    final metrics = await reg.collectMetricFamilySamples();
    format.write004(buffer, metrics);
    return Response.ok(
      buffer.toString(),
      headers: {'Content-Type': format.contentType},
    );
  });
  app.group('/api/v1', (router) {
    for (final sr in simulatedRoutes) {
      final method = sr.keys.first.toUpperCase();
      final path = sr.values.first;
      router.add(method, path, simulatedWork);
    }
  },middleware: simulatedMiddleware);
}
class RouterContext {
  final Router _router;
  final String basePath;
  final Middleware? middleware;
  RouterContext(
    this._router, {
    required this.basePath,
    this.middleware,
  });
  void add(
      String verb, String route, FutureOr<Response> Function(Request) handler) {
    if (middleware != null) {
      _router.add(verb, basePath + route, middleware!(handler));
    } else {
      _router.add(verb, basePath + route, handler);
    }
  }
}
extension RouterExtension on Router {
  void group(String basePath, Function(RouterContext) callback,
      {Middleware? middleware}) {
    final ctx = RouterContext(this, basePath: basePath);
    callback(ctx);
  }
}
FutureOr<Response> Function(Request) simulatedMiddleware(innerHandler) {
  return (request) async {
    final resp = await innerHandler(request);
    return resp;
  };
}
Future<Response> simulatedWork(Request request) async {
  try {
    final listItems = List.generate(150, (int index) => {'name': 'Jon_$index'});
    return Response.ok(
      jsonEncode(listItems),
      headers: {'Content-Type': 'application/json;charset=utf-8'},
    );
  } catch (e, s) {
    print('simulatedWork@all $e $s');
    return Response.badRequest();
  }
}
final simulatedRoutes = [
  {'get': '/administracao/paises'},
  {'get': '/administracao/ufs'},
  {'get': '/administracao/municipios'},
  {'get': '/administracao/modulos'},
  {'get': '/administracao/permissoes/:numCgm/:anoExercicio'},
  {'put': '/administracao/permissoes/:numCgm/:anoExercicio'},
  {'get': '/administracao/escolaridades'},
  {'get': '/administracao/tiposlogradouro'},
  {'get': '/administracao/orgaos'},
  {'get': '/administracao/unidades'},
  {'get': '/administracao/departamentos'},
  {'get': '/administracao/setores'},
  {'get': '/administracao/gestao'},
  {'get': '/administracao/usuarios'},
  {'get': '/administracao/usuarios/:numcgm'},
  {'post': '/administracao/usuarios'},
  {'put': '/administracao/usuarios'},
  {'get': '/administracao/cgm'},
  {'get': '/administracao/cgm/:cgm'},
  {'get': '/administracao/auditorias'},
  {'post': '/administracao/auditorias'},
  {'get': '/administracao/configuracao'},
  {'get': '/administracao/configuracao/by/filtro'},
  {'get': '/administracao/funcionalidades'},
  {'get': '/administracao/menu/:cgm'},
  {'get': '/administracao/organograma/hierarquia'},
  {'get': '/administracao/acoes'},
  //auth
  {'post': '/change/pass'},
  {'get': '/auth/check/permissao/:cgm'},
  {'post': '/auth/login'},
  {'post': '/auth/check'},
  {'get': '/auth/check/toke'},
  //cgm
  {'get': '/cgm/full'},
  {'get': '/cgm/full/:cgm'},
  {'delete': '/cgm'},
  {'post': '/cgm/full'},
  {'post': '/cgm/full/interno'},
  {'put': '/cgm/full'},
  {'get': '/cgm/atributos'},
  {'get': '/cgm/atributos/:cgm'},
  {'get': '/cgm/categoriashabilitacao'},
  {'get': '/cgm/tiposlogradouro'},
  //
  {'get': '/estatistica/processos/ano'},
  {'get': '/estatistica/processos/periodo/setor/primero/tramite'},
  {'get': '/estatistica/processos/situacao'},
  {'get': '/estatistica/processos/classificacao'},
  {'get': '/estatistica/processos/assunto'},
  //
  {'get': '/norma/normas'},
  //
  {'get': '/protocolo/processos/favoritos/cgm/:cgm'},
  {'post': '/protocolo/processos/favoritos'},
  {'post': '/protocolo/processos/favoritos/:codProcesso/:anoExercicio'},
  {'put': '/protocolo/processos/favoritos'},
  {'delete': '/protocolo/processos/favoritos/:id'},
  {'delete': '/protocolo/processos/favoritos/:codProcesso/:anoExercicio'},
  {'get': '/protocolo/acoes/favoritas/cgm/:cgm'},
  {'post': '/protocolo/acoes/favoritas'},
  {'post': '/protocolo/acoes/favoritas/:codAcao'},
  {'put': '/protocolo/acoes/favoritas'},
  {'delete': '/protocolo/acoes/favoritas/:id'},
  {'delete': '/protocolo/acoes/favoritas/:codAcao'},
  {'get': '/protocolo/assuntos'},
  {'post': '/protocolo/assuntos'},
  {'put': '/protocolo/assuntos'},
  {'delete': '/protocolo/assuntos'},
  {'get': '/protocolo/assuntos/:codAssunto/:codClassificacao'},
  {'get': '/protocolo/classificacoes'},
  {'post': '/protocolo/classificacoes'},
  {'put': '/protocolo/classificacoes'},
  {'delete': '/protocolo/classificacoes'},
  {'get': '/protocolo/despachospadrao'},
  {'post': '/protocolo/despachospadrao'},
  {'put': '/protocolo/despachospadrao'},
  {'delete': '/protocolo/despachospadrao'},
  {'get': '/protocolo/tramites'},
  {'post': '/protocolo/tramites'},
  {
    'put':
        '/protocolo/tramites/:codClassiOld/:codAssuntoOld/:ordemOld/:exercicioOld'
  },
  {'delete': '/protocolo/tramites'},
  {'get': '/protocolo/processos/:anoExercicio/:codProcesso'},
  {'get': '/protocolo/processos/em/apenso/:anoExercicio/:codProcesso'},
  {'get': '/protocolo/processos/apenso/a/:anoExercicio/:codProcesso'},
  {'get': '/protocolo/processos/andamentos/:anoExercicio/:codProcesso'},
  {
    'get':
        '/protocolo/processos/despachos/:anoExercicio/:codProcesso/:codAndamento/:codUsuario/:timestamp'
  },
  {'get': '/protocolo/processos'},
  {'get': '/protocolo/processos/areceber'},
  {'get': '/protocolo/processos/aemcaminhar'},
  {'get': '/protocolo/processos/byfiltros'},
  {'get': '/protocolo/processos/aapensara'},
  {'get': '/protocolo/processos/adesapensar'},
  {'get': '/protocolo/processos/adespachar'},
  {'get': '/protocolo/processos/aalterar'},
  {'get': '/protocolo/processos/acancelar'},
  {'get': '/protocolo/processos/aarquivar'},
  {'get': '/protocolo/processos/adesarquivar'},
  {'post': '/protocolo/processos'},
  {'post': '/protocolo/processos/implantar'},
  {'put': '/protocolo/processos'},
  {'post': '/protocolo/processos/receber/lote'},
  {'post': '/protocolo/processos/despachar/lote'},
  {'post': '/protocolo/processos/encaminhar/lote'},
  {'post': '/protocolo/processos/cancelarencaminhamento/lote'},
  {'post': '/protocolo/processos/apensar/lote'},
  {'post': '/protocolo/processos/desapensar/lote'},
  {'post': '/protocolo/processos/arquivar/lote'},
  {'post': '/protocolo/processos/desarquivar/lote'},
  {'post': '/protocolo/processos/anexos'},
  {'get': '/protocolo/processos/anexos/:codProcesso/:anoExercicio'},
  {'get': '/protocolo/situacoes'},
  {'get': '/protocolo/historicoarquivamento'},
  {'post': '/protocolo/historicoarquivamento'},
  {'put': '/protocolo/historicoarquivamento'},
  {'delete': '/protocolo/historicoarquivamento'},
  {'get': '/protocolo/listagemprocessos'},
  {'post': '/protocolo/listagemprocessos'},
  {'get': '/protocolo/documentos'},
  {'post': '/protocolo/documentos'},
  {'put': '/protocolo/documentos'},
  {'delete': '/protocolo/documentos'},
  {'get': '/protocolo/atributosprotocolo'},
  {'post': '/protocolo/atributosprotocolo'},
  {'put': '/protocolo/atributosprotocolo'},
  {'delete': '/protocolo/atributosprotocolo'},
  {'get': '/protocolo/processos/public/site/:anoExercicio/:codProcesso'},
];

Middleware logRequestsCustom(
        {void Function(String message, bool isError)? logger}) =>
    (innerHandler) {
      final theLogger = logger ?? _defaultLogger;
      return (request) {
        var startTime = DateTime.now();
        var watch = Stopwatch()..start();
        return Future.sync(() => innerHandler(request)).then((response) {
          var msg = _message(startTime, response.statusCode,
              request.requestedUri, request.method, watch.elapsed);
          theLogger(msg, false);
          return response;
        }, onError: (Object error, StackTrace stackTrace) {
          if (error is HijackException) throw error;
          var msg = _errorMessage(startTime, request.requestedUri,
              request.method, watch.elapsed, error, stackTrace);
          theLogger(msg, true);
          // ignore: only_throw_errors
          throw error;
        });
      };
    };

String _formatQuery(String query) {
  return query == '' ? '' : '?$query';
}

String _message(DateTime requestTime, int statusCode, Uri requestedUri,
    String method, Duration elapsedTime) {
  return '${requestTime.toIso8601String()} '
      '${elapsedTime.toString().padLeft(15)} '
      '${method.padRight(7)} [$statusCode] ' // 7 - longest standard HTTP method
      '${requestedUri.path}${_formatQuery(requestedUri.query)}'
      '  isolate: ${Isolate.current.debugName}';
}

String _errorMessage(DateTime requestTime, Uri requestedUri, String method,
    Duration elapsedTime, Object error, StackTrace? stack) {
  var chain = Chain.current();
  if (stack != null) {
    chain = Chain.forTrace(stack)
        .foldFrames((frame) => frame.isCore || frame.package == 'shelf')
        .terse;
  }

  var msg = '$requestTime\t$elapsedTime\t$method\t${requestedUri.path}'
      '${_formatQuery(requestedUri.query)}\n$error';

  return '$msg\n$chain';
}

void _defaultLogger(String msg, bool isError) {
  if (isError) {
    print('[ERROR] $msg');
  } else {
    print(msg);
  }
}
insinfo commented 7 months ago

I saw in the Runner code that Zone and pub_sub are being used, what are they used for?

dukefirehawk commented 7 months ago
insinfo commented 7 months ago

@dukefirehawk Sorry for expressing myself poorly, English is not my native language, what I meant to say is more specifically in the context of Angel. Why does Angel need Zone and pubsub? Which angel feature depends on this? Because I removed the zone and pubsub from the Runner and the Angel ran apparently normally, In the context of Angel, the Zone is being used to isolate unhandled Exception, to prevent the application from terminating if an exception occurs? And what is pubsub for?

dukefirehawk commented 7 months ago

You are right. Zone is to prevent unexpected exception from shutting down the entire application. To the best of my knowledge pub_sub is to facilitate communication between main isolate and spawned isolates.

insinfo commented 7 months ago

I opened an issue in the dart SDK repository, pointing out this CRASH and @mraleph discovered the problem and it has already been fixed in dart 2.19. https://github.com/dart-lang/sdk/issues/53984

To the best of my knowledge pub_sub is to facilitate communication between main isolate and spawned isolates.

Do you know if Angel uses this somewhere or if it is for Angel's consumer user to use it? Could this be used to capture metrics to get the number of requests per second from all isolates?

dukefirehawk commented 7 months ago

Good to know that it is a resolved bug in the Dart SDK. angel3_production is using it, see IsolateAdapter. It is possible to be used for capturing metrics. Anyway I've started looking into performance tuning.