dce-reactkit 3.2.0-beta.3 → 3.2.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,6 +23,7 @@ import LogSource from '../types/LogSource';
23
23
  import LogTypeSpecificInfo from '../types/Log/LogTypeSpecificInfo';
24
24
  import LogMainInfo from '../types/Log/LogMainInfo';
25
25
  import LogSourceSpecificInfo from '../types/Log/LogSourceSpecificInfo';
26
+ import LogBuiltInCategory from '../types/LogBuiltInCategory';
26
27
 
27
28
  /**
28
29
  * Generate an express API route handler
@@ -469,109 +470,166 @@ const genRouteHandler = (
469
470
  // that indicates that this is actually a client event, but we don't
470
471
  // include that in the LogFunction type because this is internal and
471
472
  // hidden from users
473
+ try {
474
+ // Parse user agent
475
+ const {
476
+ browser,
477
+ device,
478
+ } = parseUserAgent(req.headers['user-agent']);
479
+
480
+ // Get time info in ET
481
+ const {
482
+ timestamp,
483
+ year,
484
+ month,
485
+ day,
486
+ hour,
487
+ minute,
488
+ } = getTimeInfoInET();
489
+
490
+ // Main log info
491
+ const mainLogInfo: LogMainInfo = {
492
+ id: `${launchInfo.userId}-${Date.now()}-${Math.floor(Math.random() * 100000)}-${Math.floor(Math.random() * 100000)}`,
493
+ userFirstName: launchInfo.userFirstName,
494
+ userLastName: launchInfo.userLastName,
495
+ userEmail: launchInfo.userEmail,
496
+ userId: launchInfo.userId,
497
+ isLearner: !!launchInfo.isLearner,
498
+ isAdmin: !!launchInfo.isAdmin,
499
+ isTTM: !!launchInfo.isTTM,
500
+ courseId: launchInfo.courseId,
501
+ courseName: launchInfo.courseName,
502
+ browser,
503
+ device,
504
+ year,
505
+ month,
506
+ day,
507
+ hour,
508
+ minute,
509
+ timestamp,
510
+ category: (
511
+ typeof opts.category === 'string'
512
+ ? opts.category
513
+ : opts.category.name
514
+ ),
515
+ subcategory: (
516
+ typeof opts.category === 'string'
517
+ ? opts.subcategory
518
+ : ((opts.subcategory as any) ?? {}).name
519
+ ),
520
+ tags: opts.tags ?? [],
521
+ metadata: opts.metadata ?? {},
522
+ };
523
+
524
+ // Type-specific info
525
+ const typeSpecificInfo: LogTypeSpecificInfo = (
526
+ ('error' in opts && opts.error)
527
+ ? {
528
+ type: LogType.Error,
529
+ errorMessage: opts.error.message ?? 'Unknown message',
530
+ errorCode: opts.error.code ?? ReactKitErrorCode.NoCode,
531
+ errorStack: opts.error.stack ?? 'No stack',
532
+ }
533
+ : {
534
+ type: LogType.Action,
535
+ target: (opts as any).target ?? 'Unknown',
536
+ action: (opts as any).action ?? 'Unknown'
537
+ }
538
+ );
472
539
 
473
- // Parse user agent
474
- const {
475
- browser,
476
- device,
477
- } = parseUserAgent(req.headers['user-agent']);
478
-
479
- // Get time info in ET
480
- const {
481
- timestamp,
482
- year,
483
- month,
484
- day,
485
- hour,
486
- minute,
487
- } = getTimeInfoInET();
488
-
489
- // Main log info
490
- const mainLogInfo: LogMainInfo = {
491
- id: `${launchInfo.userId}-${Date.now()}-${Math.floor(Math.random() * 100000)}-${Math.floor(Math.random() * 100000)}`,
492
- userFirstName: launchInfo.userFirstName,
493
- userLastName: launchInfo.userLastName,
494
- userEmail: launchInfo.userEmail,
495
- userId: launchInfo.userId,
496
- isLearner: !!launchInfo.isLearner,
497
- isAdmin: !!launchInfo.isAdmin,
498
- isTTM: !!launchInfo.isTTM,
499
- courseId: launchInfo.courseId,
500
- courseName: launchInfo.courseName,
501
- browser,
502
- device,
503
- year,
504
- month,
505
- day,
506
- hour,
507
- minute,
508
- timestamp,
509
- category: (
510
- typeof opts.category === 'string'
511
- ? opts.category
512
- : opts.category.name
513
- ),
514
- subcategory: (
515
- typeof opts.category === 'string'
516
- ? opts.subcategory
517
- : ((opts.subcategory as any) ?? { name: 'none' }).name
518
- ),
519
- tags: opts.tags ?? [],
520
- metadata: opts.metadata ?? {},
521
- };
522
-
523
- // Type-specific info
524
- const typeSpecificInfo: LogTypeSpecificInfo = (
525
- ('error' in opts && opts.error)
526
- ? {
527
- type: LogType.Error,
528
- errorMessage: opts.error.message ?? 'Unknown message',
529
- errorCode: opts.error.code ?? ReactKitErrorCode.NoCode,
530
- errorStack: opts.error.stack ?? 'No stack',
531
- }
532
- : {
533
- type: LogType.Action,
534
- target: (opts as any).target ?? 'Unknown',
535
- action: (opts as any).action ?? 'Unknown'
536
- }
537
- );
538
-
539
- // Source-specific info
540
- const sourceSpecificInfo: LogSourceSpecificInfo = (
541
- (opts as any).overrideAsClientEvent
542
- ? {
543
- source: LogSource.Client,
544
- }
545
- : {
546
- source: LogSource.Server,
547
- routePath: req.path,
548
- routeTemplate: req.route.path,
549
- }
550
- );
540
+ // Source-specific info
541
+ const sourceSpecificInfo: LogSourceSpecificInfo = (
542
+ (opts as any).overrideAsClientEvent
543
+ ? {
544
+ source: LogSource.Client,
545
+ }
546
+ : {
547
+ source: LogSource.Server,
548
+ routePath: req.path,
549
+ routeTemplate: req.route.path,
550
+ }
551
+ );
551
552
 
552
- // Build log event
553
- const log: Log = {
554
- ...mainLogInfo,
555
- ...typeSpecificInfo,
556
- ...sourceSpecificInfo,
557
- };
558
-
559
- // Either print to console or save to db
560
- const logCollection = internalGetLogCollection();
561
- if (logCollection) {
562
- // Store to the log collection
563
- await logCollection.insert(log);
564
- } else {
565
- // Print to console
566
- if (log.type === LogType.Error) {
567
- console.error('dce-reactkit error log:', log);
553
+ // Build log event
554
+ const log: Log = {
555
+ ...mainLogInfo,
556
+ ...typeSpecificInfo,
557
+ ...sourceSpecificInfo,
558
+ };
559
+
560
+ // Either print to console or save to db
561
+ const logCollection = internalGetLogCollection();
562
+ if (logCollection) {
563
+ // Store to the log collection
564
+ await logCollection.insert(log);
568
565
  } else {
569
- console.log('dce-reactkit action log:', log);
566
+ // Print to console
567
+ if (log.type === LogType.Error) {
568
+ console.error('dce-reactkit error log:', log);
569
+ } else {
570
+ console.log('dce-reactkit action log:', log);
571
+ }
570
572
  }
571
- }
572
573
 
573
- // Return log entry
574
- return log;
574
+ // Return log entry
575
+ return log;
576
+ } catch (err) {
577
+ // Print because we cannot store the error
578
+ console.error('Could not log the following:', opts);
579
+
580
+ // Create a dummy log to return
581
+ const dummyMainInfo: LogMainInfo = {
582
+ id: '-1',
583
+ userFirstName: 'Unknown',
584
+ userLastName: 'Unknown',
585
+ userEmail: 'unknown@harvard.edu',
586
+ userId: 1,
587
+ isLearner: false,
588
+ isAdmin: false,
589
+ isTTM: false,
590
+ courseId: 1,
591
+ courseName: 'Unknown',
592
+ browser: {
593
+ name: 'Unknown',
594
+ version: 'Unknown',
595
+ },
596
+ device: {
597
+ isMobile: false,
598
+ os: 'Unknown',
599
+ },
600
+ year: 1,
601
+ month: 1,
602
+ day: 1,
603
+ hour: 1,
604
+ minute: 1,
605
+ timestamp: Date.now(),
606
+ tags: [],
607
+ metadata: {},
608
+ category: LogBuiltInCategory.Uncategorized,
609
+ subcategory: LogBuiltInCategory.Uncategorized,
610
+ };
611
+
612
+ const dummyTypeSpecificInfo: LogTypeSpecificInfo = {
613
+ type: LogType.Error,
614
+ errorMessage: 'Unknown',
615
+ errorCode: 'Unknown',
616
+ errorStack: 'No Stack',
617
+ };
618
+
619
+ const dummySourceSpecificInfo: LogSourceSpecificInfo = {
620
+ source: LogSource.Server,
621
+ routePath: req.path,
622
+ routeTemplate: req.route.path,
623
+ };
624
+
625
+ const log: Log = {
626
+ ...dummyMainInfo,
627
+ ...dummyTypeSpecificInfo,
628
+ ...dummySourceSpecificInfo,
629
+ };
630
+
631
+ return log;
632
+ }
575
633
  };
576
634
 
577
635
  /*------------------------------------------------------------------------*/
@@ -625,6 +683,22 @@ const genRouteHandler = (
625
683
  ) => {
626
684
  const html = genErrorPage(opts);
627
685
  send(html, opts.status ?? 500);
686
+
687
+ // Log
688
+ logServerEvent({
689
+ category: LogBuiltInCategory.ServerRenderedErrorPage,
690
+ error: {
691
+ message: `${opts.title}: ${opts.description}`,
692
+ code: opts.code,
693
+ },
694
+ metadata: {
695
+ title: opts.title,
696
+ description: opts.description,
697
+ code: opts.code,
698
+ pageTitle: opts.pageTitle,
699
+ status: opts.status ?? 500,
700
+ },
701
+ });
628
702
  };
629
703
 
630
704
  // Call the handler
@@ -649,7 +723,15 @@ const genRouteHandler = (
649
723
  } catch (err) {
650
724
  // Send error to client (only if next wasn't called)
651
725
  if (!responseSent) {
652
- return handleError(res, err);
726
+ handleError(res, err);
727
+
728
+ // Log server-side error
729
+ logServerEvent({
730
+ category: LogBuiltInCategory.ServerEndpointError,
731
+ error: err,
732
+ });
733
+
734
+ return;
653
735
  }
654
736
 
655
737
  // Log error that was not responded with
package/src/index.ts CHANGED
@@ -63,6 +63,7 @@ import Log from './types/Log';
63
63
  import LogType from './types/LogType';
64
64
  import LogSource from './types/LogSource';
65
65
  import LogAction from './types/LogAction';
66
+ import LogBuiltInCategory from './types/LogBuiltInCategory';
66
67
 
67
68
  // Component-specific-types
68
69
  import PickableItem from './components/ItemPicker/types/PickableItem';
@@ -135,6 +136,7 @@ export {
135
136
  LogType,
136
137
  LogSource,
137
138
  LogAction,
139
+ LogBuiltInCategory,
138
140
  // Component-specific-types
139
141
  PickableItem,
140
142
  // Server types
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Built-in categories for logs
3
+ * @author Gabe Abrams
4
+ */
5
+ enum LogBuiltInCategory {
6
+ Uncategorized = 'n/a',
7
+ ServerRenderedErrorPage = '_server-rendered-error-page',
8
+ ServerEndpointError = '_server-endpoint-error',
9
+ };
10
+
11
+ export default LogBuiltInCategory;