whatap 0.5.11 → 0.5.13
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.
- package/lib/conf/config-default.js +2 -0
- package/lib/core/agent.js +4 -1
- package/lib/counter/counter-manager.js +4 -0
- package/lib/counter/task/metering-info.js +118 -0
- package/lib/observers/http-observer.js +1 -0
- package/lib/observers/oracle-observer.js +656 -0
- package/lib/observers/prisma-observer.js +20 -269
- package/lib/observers/socket.io-observer.js +213 -74
- package/lib/observers/websocket-observer.js +164 -67
- package/lib/pack/apenum.js +8 -0
- package/lib/pack/otype.js +7 -0
- package/lib/pack/tagcount-pack.js +51 -50
- package/lib/util/dateutil.js +33 -1
- package/lib/util/escape-literal-sql.js +5 -5
- package/package.json +2 -2
|
@@ -365,8 +365,8 @@ PrismaObserver.prototype.hookUseMiddleware = function(prismaInstance) {
|
|
|
365
365
|
ctx.footprint(`Prisma ${modelName}.${action} Start`);
|
|
366
366
|
ctx.sql_count = (ctx.sql_count || 0) + 1;
|
|
367
367
|
|
|
368
|
-
//
|
|
369
|
-
const queryInfo = `Prisma ${
|
|
368
|
+
// Prisma 쿼리 정보 직접 사용 (SQL 변환 없이)
|
|
369
|
+
const queryInfo = `Prisma ${modelName}.${action}`;
|
|
370
370
|
const queryHash = HashUtil.hashFromString(queryInfo);
|
|
371
371
|
|
|
372
372
|
DataTextAgent.SQL.add(queryHash, queryInfo);
|
|
@@ -388,6 +388,7 @@ PrismaObserver.prototype.hookUseMiddleware = function(prismaInstance) {
|
|
|
388
388
|
try {
|
|
389
389
|
result = await next(params);
|
|
390
390
|
|
|
391
|
+
// Raw 쿼리 처리
|
|
391
392
|
if (action === "queryRaw" || action === "executeRaw" || action === "queryRawUnsafe" || action === "executeRawUnsafe") {
|
|
392
393
|
// SQL 문자열 추출
|
|
393
394
|
let sqlString = "";
|
|
@@ -408,10 +409,6 @@ PrismaObserver.prototype.hookUseMiddleware = function(prismaInstance) {
|
|
|
408
409
|
var psql = escapeLiteral(sqlString);
|
|
409
410
|
if (psql != null) {
|
|
410
411
|
sql_step.hash = psql.sql;
|
|
411
|
-
// CRUD 타입 설정 (S: Select, U: Update 등)
|
|
412
|
-
// if (psql.type) {
|
|
413
|
-
// sql_step.crud = psql.type.charCodeAt(0);
|
|
414
|
-
// }
|
|
415
412
|
}
|
|
416
413
|
|
|
417
414
|
// 추가 SQL 정보 처리
|
|
@@ -451,9 +448,8 @@ PrismaObserver.prototype.hookUseMiddleware = function(prismaInstance) {
|
|
|
451
448
|
recordCount = 1;
|
|
452
449
|
}
|
|
453
450
|
|
|
454
|
-
if
|
|
455
|
-
|
|
456
|
-
const sqlHashToUse = psql ? psql.sql : queryHash;
|
|
451
|
+
if(psql && psql.sql){
|
|
452
|
+
const sqlHashToUse = psql.sql;
|
|
457
453
|
|
|
458
454
|
var result_step = new ResultSetStep();
|
|
459
455
|
result_step.start_time = ctx.getElapsedTime();
|
|
@@ -484,23 +480,21 @@ PrismaObserver.prototype.hookUseMiddleware = function(prismaInstance) {
|
|
|
484
480
|
recordCount = 1;
|
|
485
481
|
}
|
|
486
482
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
ctx.profile.push(result_step);
|
|
483
|
+
var result_step = new ResultSetStep();
|
|
484
|
+
result_step.start_time = ctx.getElapsedTime();
|
|
485
|
+
result_step.elapsed = 0;
|
|
486
|
+
result_step.fetch = recordCount;
|
|
487
|
+
result_step.sqlhash = queryHash;
|
|
488
|
+
result_step.dbc = dbc_hash;
|
|
489
|
+
ctx.profile.push(result_step);
|
|
495
490
|
|
|
496
|
-
|
|
497
|
-
|
|
491
|
+
ctx.rs_count = ctx.rs_count ? ctx.rs_count + recordCount : recordCount;
|
|
492
|
+
ctx.rs_time = ctx.rs_time ? ctx.rs_time + sql_step.elapsed : sql_step.elapsed;
|
|
498
493
|
|
|
499
|
-
|
|
500
|
-
|
|
494
|
+
MeterSql.addFetch(result_step.dbc, result_step.fetch, 0);
|
|
495
|
+
StatSql.addFetch(result_step.dbc, result_step.sqlhash, result_step.fetch, 0);
|
|
501
496
|
|
|
502
|
-
|
|
503
|
-
}
|
|
497
|
+
TraceSQL.isTooManyRecords(sql_step, result_step.fetch, ctx);
|
|
504
498
|
}
|
|
505
499
|
|
|
506
500
|
// 수정된 레코드 수 처리 (create, update, delete 등)
|
|
@@ -512,252 +506,9 @@ PrismaObserver.prototype.hookUseMiddleware = function(prismaInstance) {
|
|
|
512
506
|
}
|
|
513
507
|
}
|
|
514
508
|
|
|
515
|
-
//
|
|
516
|
-
if (
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
try {
|
|
520
|
-
// 모델 메서드를 SQL 스타일로 변환
|
|
521
|
-
let sqlStyleQuery = "";
|
|
522
|
-
|
|
523
|
-
// 액션에 따라 SQL 명령 결정
|
|
524
|
-
if (action.startsWith('find')) {
|
|
525
|
-
sqlStyleQuery = "SELECT ";
|
|
526
|
-
|
|
527
|
-
// select 필드가 있는 경우 해당 필드 사용
|
|
528
|
-
if (params.args && params.args.select) {
|
|
529
|
-
const fields = Object.keys(params.args.select)
|
|
530
|
-
.filter(key => params.args.select[key] === true);
|
|
531
|
-
|
|
532
|
-
if (fields.length > 0) {
|
|
533
|
-
sqlStyleQuery += fields.join(", ");
|
|
534
|
-
} else {
|
|
535
|
-
sqlStyleQuery += "*";
|
|
536
|
-
}
|
|
537
|
-
} else {
|
|
538
|
-
sqlStyleQuery += "*";
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
sqlStyleQuery += ` FROM ${modelName}`;
|
|
542
|
-
|
|
543
|
-
// where 조건 추가
|
|
544
|
-
if (params.args && params.args.where) {
|
|
545
|
-
const conditions = [];
|
|
546
|
-
for (const [key, value] of Object.entries(params.args.where)) {
|
|
547
|
-
if (typeof value === 'object' && value !== null) {
|
|
548
|
-
// 복합 조건(contains, startsWith 등)
|
|
549
|
-
for (const [op, val] of Object.entries(value)) {
|
|
550
|
-
let sqlOp = "";
|
|
551
|
-
|
|
552
|
-
// Prisma 연산자를 SQL 연산자로 변환
|
|
553
|
-
switch (op) {
|
|
554
|
-
case 'equals': sqlOp = '='; break;
|
|
555
|
-
case 'not': sqlOp = '!='; break;
|
|
556
|
-
case 'in': sqlOp = 'IN'; break;
|
|
557
|
-
case 'notIn': sqlOp = 'NOT IN'; break;
|
|
558
|
-
case 'lt': sqlOp = '<'; break;
|
|
559
|
-
case 'lte': sqlOp = '<='; break;
|
|
560
|
-
case 'gt': sqlOp = '>'; break;
|
|
561
|
-
case 'gte': sqlOp = '>='; break;
|
|
562
|
-
case 'contains': sqlOp = 'LIKE'; break;
|
|
563
|
-
case 'startsWith': sqlOp = 'LIKE'; break;
|
|
564
|
-
case 'endsWith': sqlOp = 'LIKE'; break;
|
|
565
|
-
default: sqlOp = op;
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
let sqlVal = val;
|
|
569
|
-
if (op === 'contains') {
|
|
570
|
-
sqlVal = `'%${val}%'`;
|
|
571
|
-
} else if (op === 'startsWith') {
|
|
572
|
-
sqlVal = `'${val}%'`;
|
|
573
|
-
} else if (op === 'endsWith') {
|
|
574
|
-
sqlVal = `'%${val}'`;
|
|
575
|
-
} else if (typeof val === 'string') {
|
|
576
|
-
sqlVal = `'${val}'`;
|
|
577
|
-
} else if (Array.isArray(val)) {
|
|
578
|
-
sqlVal = `(${val.map(v => typeof v === 'string' ? `'${v}'` : v).join(', ')})`;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
conditions.push(`${key} ${sqlOp} ${sqlVal}`);
|
|
582
|
-
}
|
|
583
|
-
} else {
|
|
584
|
-
// 단순 조건
|
|
585
|
-
let formattedValue = typeof value === 'string' ? `'${value}'` : value;
|
|
586
|
-
conditions.push(`${key} = ${formattedValue}`);
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
if (conditions.length > 0) {
|
|
591
|
-
sqlStyleQuery += ` WHERE ${conditions.join(' AND ')}`;
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// 정렬 조건 추가
|
|
596
|
-
if (params.args && params.args.orderBy) {
|
|
597
|
-
const orderClauses = [];
|
|
598
|
-
|
|
599
|
-
if (Array.isArray(params.args.orderBy)) {
|
|
600
|
-
for (const item of params.args.orderBy) {
|
|
601
|
-
for (const [field, dir] of Object.entries(item)) {
|
|
602
|
-
orderClauses.push(`${field} ${dir}`);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
} else {
|
|
606
|
-
for (const [field, dir] of Object.entries(params.args.orderBy)) {
|
|
607
|
-
orderClauses.push(`${field} ${dir}`);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
if (orderClauses.length > 0) {
|
|
612
|
-
sqlStyleQuery += ` ORDER BY ${orderClauses.join(', ')}`;
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
// 페이징 정보 추가
|
|
617
|
-
if (params.args) {
|
|
618
|
-
if (params.args.skip !== undefined) {
|
|
619
|
-
sqlStyleQuery += ` OFFSET ${params.args.skip}`;
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
if (params.args.take !== undefined) {
|
|
623
|
-
sqlStyleQuery += ` LIMIT ${params.args.take}`;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
} else if (action.startsWith('create')) {
|
|
628
|
-
sqlStyleQuery = `INSERT INTO ${modelName}`;
|
|
629
|
-
|
|
630
|
-
if (params.args && params.args.data) {
|
|
631
|
-
const columns = [];
|
|
632
|
-
const values = [];
|
|
633
|
-
|
|
634
|
-
for (const [key, val] of Object.entries(params.args.data)) {
|
|
635
|
-
columns.push(key);
|
|
636
|
-
if (typeof val === 'string') {
|
|
637
|
-
values.push(`'${val}'`);
|
|
638
|
-
} else if (val === null) {
|
|
639
|
-
values.push('NULL');
|
|
640
|
-
} else if (typeof val === 'object') {
|
|
641
|
-
values.push(`'${JSON.stringify(val)}'`);
|
|
642
|
-
} else {
|
|
643
|
-
values.push(val);
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
sqlStyleQuery += ` (${columns.join(', ')}) VALUES (${values.join(', ')})`;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
} else if (action.startsWith('update')) {
|
|
651
|
-
sqlStyleQuery = `UPDATE ${modelName}`;
|
|
652
|
-
|
|
653
|
-
if (params.args && params.args.data) {
|
|
654
|
-
const setExpressions = [];
|
|
655
|
-
|
|
656
|
-
for (const [key, val] of Object.entries(params.args.data)) {
|
|
657
|
-
let formattedValue;
|
|
658
|
-
if (typeof val === 'string') {
|
|
659
|
-
formattedValue = `'${val}'`;
|
|
660
|
-
} else if (val === null) {
|
|
661
|
-
formattedValue = 'NULL';
|
|
662
|
-
} else if (typeof val === 'object') {
|
|
663
|
-
formattedValue = `'${JSON.stringify(val)}'`;
|
|
664
|
-
} else {
|
|
665
|
-
formattedValue = val;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
setExpressions.push(`${key} = ${formattedValue}`);
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
if (setExpressions.length > 0) {
|
|
672
|
-
sqlStyleQuery += ` SET ${setExpressions.join(', ')}`;
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
// where 조건 추가
|
|
677
|
-
if (params.args && params.args.where) {
|
|
678
|
-
const conditions = [];
|
|
679
|
-
for (const [key, value] of Object.entries(params.args.where)) {
|
|
680
|
-
if (typeof value === 'object' && value !== null) {
|
|
681
|
-
for (const [op, val] of Object.entries(value)) {
|
|
682
|
-
let sqlOp = op === 'equals' ? '=' : op;
|
|
683
|
-
let sqlVal = typeof val === 'string' ? `'${val}'` : val;
|
|
684
|
-
conditions.push(`${key} ${sqlOp} ${sqlVal}`);
|
|
685
|
-
}
|
|
686
|
-
} else {
|
|
687
|
-
let formattedValue = typeof value === 'string' ? `'${value}'` : value;
|
|
688
|
-
conditions.push(`${key} = ${formattedValue}`);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
if (conditions.length > 0) {
|
|
693
|
-
sqlStyleQuery += ` WHERE ${conditions.join(' AND ')}`;
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
} else if (action.startsWith('delete')) {
|
|
698
|
-
sqlStyleQuery = `DELETE FROM ${modelName}`;
|
|
699
|
-
|
|
700
|
-
// where 조건 추가
|
|
701
|
-
if (params.args && params.args.where) {
|
|
702
|
-
const conditions = [];
|
|
703
|
-
for (const [key, value] of Object.entries(params.args.where)) {
|
|
704
|
-
if (typeof value === 'object' && value !== null) {
|
|
705
|
-
for (const [op, val] of Object.entries(value)) {
|
|
706
|
-
let sqlOp = op === 'equals' ? '=' : op;
|
|
707
|
-
let sqlVal = typeof val === 'string' ? `'${val}'` : val;
|
|
708
|
-
conditions.push(`${key} ${sqlOp} ${sqlVal}`);
|
|
709
|
-
}
|
|
710
|
-
} else {
|
|
711
|
-
let formattedValue = typeof value === 'string' ? `'${value}'` : value;
|
|
712
|
-
conditions.push(`${key} = ${formattedValue}`);
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
if (conditions.length > 0) {
|
|
717
|
-
sqlStyleQuery += ` WHERE ${conditions.join(' AND ')}`;
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
} else {
|
|
721
|
-
// 기타 액션은 기본 형식으로
|
|
722
|
-
sqlStyleQuery = `${action.toUpperCase()} ${modelName}`;
|
|
723
|
-
|
|
724
|
-
if (params.args) {
|
|
725
|
-
sqlStyleQuery += ` ${JSON.stringify(params.args)}`;
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
// 생성된 SQL 쿼리에 escapeLiteral 적용하여 처리
|
|
730
|
-
try {
|
|
731
|
-
var psql = escapeLiteral(sqlStyleQuery);
|
|
732
|
-
if (psql != null) {
|
|
733
|
-
sql_step.hash = psql.sql;
|
|
734
|
-
// CRUD 타입 설정
|
|
735
|
-
if (psql.type) {
|
|
736
|
-
sql_step.crud = psql.type.charCodeAt(0);
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
// 추가 SQL 정보 처리
|
|
741
|
-
var els = new EscapeLiteralSQL(sqlStyleQuery);
|
|
742
|
-
els.process();
|
|
743
|
-
|
|
744
|
-
// SQL 파라미터 처리
|
|
745
|
-
if (conf.profile_sql_param_enabled) {
|
|
746
|
-
sql_step.setTrue(1);
|
|
747
|
-
var crc = {value: 0};
|
|
748
|
-
sql_step.p1 = toParamBytes(psql.param, crc);
|
|
749
|
-
|
|
750
|
-
// 원래 인자를 파라미터로 추가
|
|
751
|
-
const paramsString = JSON.stringify(params.args || {});
|
|
752
|
-
sql_step.p2 = toParamBytes(paramsString, crc);
|
|
753
|
-
sql_step.pcrc = crc.value;
|
|
754
|
-
}
|
|
755
|
-
} catch (e) {
|
|
756
|
-
Logger.printError("WHATAP-306", "escapeLiteral error for model method", e, false);
|
|
757
|
-
}
|
|
758
|
-
} catch (e) {
|
|
759
|
-
Logger.printError("WHATAP-307", "Error creating SQL-style query", e, false);
|
|
760
|
-
}
|
|
509
|
+
// UPSERT 처리 추가
|
|
510
|
+
if (action === "upsert") {
|
|
511
|
+
sql_step.updated = 1; // upsert는 항상 1개의 레코드에 영향을 미침
|
|
761
512
|
}
|
|
762
513
|
|
|
763
514
|
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|