whatap 0.5.26 → 1.0.0
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/agent/darwin/arm64/whatap_nodejs +0 -0
- package/agent/linux/amd64/whatap_nodejs +0 -0
- package/agent/linux/arm64/whatap_nodejs +0 -0
- package/build.txt +4 -0
- package/lib/conf/config-default.js +3 -10
- package/lib/conf/configure.js +349 -369
- package/lib/conf/license.js +1 -1
- package/lib/control/packagectr-helper.js +3 -34
- package/lib/core/agent.js +882 -176
- package/lib/core/interceptor.js +6 -6
- package/lib/core/shimmer.js +36 -82
- package/lib/counter/counter-manager.js +8 -79
- package/lib/counter/task/activetransaction.js +17 -68
- package/lib/io/data-inputx.js +3 -13
- package/lib/io/data-outputx.js +206 -268
- package/lib/logger.js +6 -6
- package/lib/net/security-master.js +20 -139
- package/lib/observers/apollo-server-observer.js +27 -33
- package/lib/observers/global-observer.js +80 -155
- package/lib/observers/http-observer.js +236 -666
- package/lib/observers/ioredis-observer.js +294 -0
- package/lib/observers/maria-observer.js +362 -204
- package/lib/observers/mongodb-observer.js +226 -169
- package/lib/observers/mongoose-observer.js +323 -518
- package/lib/observers/mssql-observer.js +418 -177
- package/lib/observers/mysql-observer.js +449 -342
- package/lib/observers/mysql2-observer.js +358 -396
- package/lib/observers/oracle-observer.js +384 -559
- package/lib/observers/pgsql-observer.js +489 -231
- package/lib/observers/prisma-observer.js +92 -303
- package/lib/observers/process-observer.js +35 -79
- package/lib/observers/redis-observer.js +331 -166
- package/lib/observers/socket.io-observer.js +187 -226
- package/lib/observers/websocket-observer.js +301 -175
- package/lib/pack/counter-pack.js +0 -3
- package/lib/pack/log-sink-pack.js +52 -14
- package/lib/pack/tagcount-pack.js +4 -4
- package/lib/{counter/task → system}/gc-action.js +74 -27
- package/lib/trace/trace-context-manager.js +25 -113
- package/lib/trace/trace-context.js +7 -21
- package/lib/trace/trace-httpc.js +11 -17
- package/lib/trace/trace-sql.js +21 -29
- package/lib/udp/async_sender.js +119 -0
- package/lib/udp/index.js +17 -0
- package/lib/udp/packet_enum.js +52 -0
- package/lib/udp/packet_queue.js +69 -0
- package/lib/udp/packet_type_enum.js +33 -0
- package/lib/udp/param_def.js +72 -0
- package/lib/udp/udp_session.js +336 -0
- package/lib/util/escape-literal-sql.js +5 -5
- package/lib/util/hashutil.js +18 -18
- package/lib/util/keygen.js +3 -0
- package/lib/util/linkedset.js +2 -1
- package/lib/util/nodeutil.js +1 -2
- package/lib/util/sql-util.js +178 -0
- package/lib/util/trace-helper.js +91 -0
- package/lib/util/transfer.js +58 -0
- package/lib/value/map-value.js +2 -3
- package/package.json +5 -10
- package/lib/conf/conf-sys-mon.js +0 -101
- package/lib/control/cmd-config.js +0 -24
- package/lib/control/control-handler.js +0 -367
- package/lib/core/request-agent.js +0 -27
- package/lib/counter/meter/meter-activex.js +0 -67
- package/lib/counter/meter/meter-httpc.js +0 -57
- package/lib/counter/meter/meter-resource.js +0 -9
- package/lib/counter/meter/meter-service.js +0 -168
- package/lib/counter/meter/meter-socket.io.js +0 -51
- package/lib/counter/meter/meter-sql.js +0 -71
- package/lib/counter/meter/meter-users.js +0 -58
- package/lib/counter/meter.js +0 -183
- package/lib/counter/task/agentinfo.js +0 -107
- package/lib/counter/task/gcstat.js +0 -34
- package/lib/counter/task/heapmem.js +0 -25
- package/lib/counter/task/httpc.js +0 -76
- package/lib/counter/task/metering-info.js +0 -125
- package/lib/counter/task/proc-cpu.js +0 -29
- package/lib/counter/task/realtimeuser.js +0 -31
- package/lib/counter/task/res/systemECSTask.js +0 -39
- package/lib/counter/task/res/systemKubeTask.js +0 -53
- package/lib/counter/task/res/util/awsEcsClientThread.js +0 -218
- package/lib/counter/task/res/util/linuxProcStatUtil.js +0 -14
- package/lib/counter/task/res-sys-cpu.js +0 -62
- package/lib/counter/task/service.js +0 -202
- package/lib/counter/task/socketio.js +0 -30
- package/lib/counter/task/sql.js +0 -105
- package/lib/counter/task/systemperf.js +0 -43
- package/lib/data/datapack-sender.js +0 -289
- package/lib/data/dataprofile-agent.js +0 -162
- package/lib/data/datatext-agent.js +0 -135
- package/lib/data/event-level.js +0 -15
- package/lib/data/test.js +0 -49
- package/lib/data/zipprofile.js +0 -197
- package/lib/env/constants.js +0 -21
- package/lib/error/error-handler.js +0 -437
- package/lib/kube/kube-client.js +0 -144
- package/lib/lang/text-types.js +0 -58
- package/lib/logsink/line-log-util.js +0 -87
- package/lib/logsink/line-log.js +0 -12
- package/lib/logsink/log-sender.js +0 -78
- package/lib/logsink/log-tracer.js +0 -40
- package/lib/logsink/sender-util.js +0 -56
- package/lib/logsink/zip/zip-send.js +0 -177
- package/lib/net/netflag.js +0 -55
- package/lib/net/receiver.js +0 -66
- package/lib/net/sender.js +0 -141
- package/lib/net/tcp-return.js +0 -18
- package/lib/net/tcp-session.js +0 -286
- package/lib/net/tcpreq-client-proxy.js +0 -70
- package/lib/net/tcprequest-mgr.js +0 -58
- package/lib/observers/cluster-observer.js +0 -22
- package/lib/observers/express-observer.js +0 -215
- package/lib/observers/file-observer.js +0 -184
- package/lib/observers/grpc-observer.js +0 -336
- package/lib/observers/memcached-observer.js +0 -56
- package/lib/observers/mongo-observer.js +0 -317
- package/lib/observers/net-observer.js +0 -77
- package/lib/observers/promise-observer.js +0 -31
- package/lib/observers/schedule-observer.js +0 -67
- package/lib/observers/stream-observer.js +0 -19
- package/lib/observers/thrift-observer.js +0 -197
- package/lib/pack/activestack-pack.js +0 -55
- package/lib/pack/apenum.js +0 -8
- package/lib/pack/errorsnap-pack.js +0 -69
- package/lib/pack/event-pack.js +0 -54
- package/lib/pack/hitmap-pack.js +0 -63
- package/lib/pack/hitmap-pack1.js +0 -152
- package/lib/pack/netstat.js +0 -15
- package/lib/pack/otype.js +0 -7
- package/lib/pack/profile-pack.js +0 -49
- package/lib/pack/realtimeuser-pack.js +0 -41
- package/lib/pack/stat-general-pack.js +0 -96
- package/lib/pack/staterror-pack.js +0 -120
- package/lib/pack/stathttpc-pack.js +0 -66
- package/lib/pack/stathttpc-rec.js +0 -78
- package/lib/pack/statremote-pack.js +0 -46
- package/lib/pack/statservice-pack.js +0 -63
- package/lib/pack/statservice-pack1.js +0 -88
- package/lib/pack/statservice-rec.js +0 -292
- package/lib/pack/statservice-rec_dep.js +0 -151
- package/lib/pack/statsql-pack.js +0 -69
- package/lib/pack/statsql-rec.js +0 -100
- package/lib/pack/statuseragent-pack.js +0 -44
- package/lib/pack/tagctr.js +0 -15
- package/lib/pack/text-pack.js +0 -50
- package/lib/pack/time-count.js +0 -25
- package/lib/pack/websocket.js +0 -15
- package/lib/pack/zip-pack.js +0 -70
- package/lib/pii/pii-item.js +0 -31
- package/lib/pii/pii-mask.js +0 -174
- package/lib/plugin/plugin-loadermanager.js +0 -57
- package/lib/plugin/plugin.js +0 -75
- package/lib/service/tx-record.js +0 -332
- package/lib/stat/stat-error.js +0 -116
- package/lib/stat/stat-httpc.js +0 -98
- package/lib/stat/stat-remote-ip.js +0 -46
- package/lib/stat/stat-remote-ipurl.js +0 -88
- package/lib/stat/stat-sql.js +0 -113
- package/lib/stat/stat-tranx.js +0 -58
- package/lib/stat/stat-tx-caller.js +0 -160
- package/lib/stat/stat-tx-domain.js +0 -111
- package/lib/stat/stat-tx-referer.js +0 -112
- package/lib/stat/stat-useragent.js +0 -48
- package/lib/stat/timingsender.js +0 -76
- package/lib/step/activestack-step.js +0 -38
- package/lib/step/dbc-step.js +0 -36
- package/lib/step/http-stepx.js +0 -67
- package/lib/step/message-step.js +0 -40
- package/lib/step/method-stepx.js +0 -45
- package/lib/step/resultset-step.js +0 -40
- package/lib/step/securemsg-step.js +0 -44
- package/lib/step/socket-step.js +0 -46
- package/lib/step/sql-stepx.js +0 -68
- package/lib/step/sqlxtype.js +0 -16
- package/lib/step/step.js +0 -66
- package/lib/step/stepenum.js +0 -54
- package/lib/topology/link.js +0 -63
- package/lib/topology/nodeinfo.js +0 -123
- package/lib/topology/status-detector.js +0 -111
- package/lib/util/anylist.js +0 -103
- package/lib/util/cardinality/hyperloglog.js +0 -106
- package/lib/util/cardinality/murmurhash.js +0 -31
- package/lib/util/cardinality/registerset.js +0 -75
- package/lib/util/errordata.js +0 -21
- package/lib/util/iputil_x.js +0 -527
- package/lib/util/kube-util.js +0 -73
- package/lib/util/paramsecurity.js +0 -80
- package/lib/util/pre-process.js +0 -13
- package/lib/util/process-seq.js +0 -166
- package/lib/util/property-util.js +0 -36
- package/lib/util/request-queue.js +0 -70
- package/lib/util/requestdouble-queue.js +0 -72
- package/lib/util/resourceprofile.js +0 -157
- package/lib/util/stop-watch.js +0 -30
- package/lib/util/system-util.js +0 -10
- package/lib/util/userid-util.js +0 -57
|
@@ -1,583 +1,388 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2016 the WHATAP project authors. All rights reserved.
|
|
3
|
+
* Use of this source code is governed by a license that
|
|
4
|
+
* can be found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
var TraceContextManager = require('../trace/trace-context-manager'),
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const conf = require('../conf/configure');
|
|
10
|
-
const shimmer = require('../core/shimmer');
|
|
8
|
+
HashUtil = require('../util/hashutil'),
|
|
9
|
+
Logger = require('../logger'),
|
|
10
|
+
conf = require('../conf/configure'),
|
|
11
|
+
AsyncSender = require('../udp/async_sender'),
|
|
12
|
+
PacketTypeEnum = require('../udp/packet_type_enum'),
|
|
13
|
+
shimmer = require('../core/shimmer'),
|
|
14
|
+
AsyncResource = require('async_hooks').AsyncResource;
|
|
11
15
|
|
|
12
16
|
var MongooseObserver = function (agent) {
|
|
13
17
|
this.agent = agent;
|
|
14
18
|
this.packages = ['mongoose'];
|
|
15
19
|
};
|
|
16
20
|
|
|
17
|
-
var
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
'findOneAndUpdate',
|
|
33
|
-
|
|
34
|
-
'
|
|
35
|
-
'
|
|
36
|
-
'findOneAndDelete',
|
|
37
|
-
|
|
38
|
-
'
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
// 특수 메서드
|
|
42
|
-
const specialMethods = [
|
|
43
|
-
'create',
|
|
44
|
-
'insertMany',
|
|
45
|
-
'aggregate'
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
MongooseObserver.prototype.inject = function (mod, modName) {
|
|
49
|
-
var self = this;
|
|
50
|
-
|
|
51
|
-
// mongoose.connect 후킹 (연결 정보 저장)
|
|
52
|
-
shimmer.wrap(mod, 'connect', function(originalConnect) {
|
|
53
|
-
return function wrappedConnect() {
|
|
54
|
-
if (arguments[0]) {
|
|
55
|
-
dbc = arguments[0];
|
|
56
|
-
conn_dbc_hash = HashUtil.hashFromString(dbc);
|
|
57
|
-
}
|
|
58
|
-
return originalConnect.apply(this, arguments);
|
|
59
|
-
};
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// Model 생성 후킹
|
|
63
|
-
shimmer.wrap(mod, 'model', function(originalModel) {
|
|
64
|
-
return function wrappedModel() {
|
|
65
|
-
const model = originalModel.apply(this, arguments);
|
|
66
|
-
|
|
67
|
-
// 생성된 Model에 메서드 패치 적용
|
|
68
|
-
self.patchModelMethods(model);
|
|
69
|
-
|
|
70
|
-
return model;
|
|
71
|
-
};
|
|
72
|
-
});
|
|
21
|
+
var dbc_hash = 0;
|
|
22
|
+
var dbc = '';
|
|
23
|
+
|
|
24
|
+
// Mongoose 명령어 매핑
|
|
25
|
+
var MONGOOSE_COMMANDS = {
|
|
26
|
+
'create': 'CREATE',
|
|
27
|
+
'insertMany': 'INSERTMANY',
|
|
28
|
+
'find': 'FIND',
|
|
29
|
+
'findById': 'FINDBYID',
|
|
30
|
+
'findOne': 'FINDONE',
|
|
31
|
+
'countDocuments': 'COUNTDOCUMENTS',
|
|
32
|
+
'distinct': 'DISTINCT',
|
|
33
|
+
'updateMany': 'UPDATEMANY',
|
|
34
|
+
'updateOne': 'UPDATEONE',
|
|
35
|
+
'replaceOne': 'REPLACEONE',
|
|
36
|
+
'findOneAndUpdate': 'FINDONEANDUPDATE',
|
|
37
|
+
'findByIdAndUpdate': 'FINDBYIDANDUPDATE',
|
|
38
|
+
'deleteOne': 'DELETEONE',
|
|
39
|
+
'deleteMany': 'DELETEMANY',
|
|
40
|
+
'findOneAndDelete': 'FINDONEANDDELETE',
|
|
41
|
+
'findByIdAndDelete': 'FINDBYIDANDDELETE',
|
|
42
|
+
'aggregate': 'AGGREGATE'
|
|
73
43
|
};
|
|
74
44
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
collectionMethodsWithFilter.forEach(function(methodName) {
|
|
82
|
-
if (Model[methodName]) {
|
|
83
|
-
shimmer.wrap(Model, methodName, function(originalMethod) {
|
|
84
|
-
return self.createSingleFilterWrapper(originalMethod, methodName);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// 이중 필터 메서드 패치
|
|
90
|
-
collectionMethodsWithTwoFilters.forEach(function(methodName) {
|
|
91
|
-
if (Model[methodName]) {
|
|
92
|
-
shimmer.wrap(Model, methodName, function(originalMethod) {
|
|
93
|
-
return self.createDoubleFilterWrapper(originalMethod, methodName);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// aggregate 메서드 패치
|
|
99
|
-
if (Model.aggregate) {
|
|
100
|
-
shimmer.wrap(Model, 'aggregate', function(originalAggregate) {
|
|
101
|
-
return self.createAggregateWrapper(originalAggregate);
|
|
102
|
-
});
|
|
45
|
+
// DBC 정보 설정
|
|
46
|
+
function setupDbcInfo(connectionString) {
|
|
47
|
+
if (dbc_hash === 0 && connectionString) {
|
|
48
|
+
dbc = connectionString;
|
|
49
|
+
dbc_hash = HashUtil.hashFromString(dbc);
|
|
50
|
+
Logger.print('WHATAP-MONGOOSE-DBC', 'DBC setup: ' + dbc, false);
|
|
103
51
|
}
|
|
52
|
+
}
|
|
104
53
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
shimmer.wrap(Model, methodName, function(originalMethod) {
|
|
109
|
-
return self.createInsertWrapper(originalMethod, methodName);
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
MongooseObserver.prototype.createSingleFilterWrapper = function(originalMethod, methodName) {
|
|
116
|
-
var self = this;
|
|
117
|
-
|
|
118
|
-
return function wrappedSingleFilter() {
|
|
119
|
-
const ctx = TraceContextManager.getCurrentContext();
|
|
120
|
-
if (!ctx) {
|
|
121
|
-
return originalMethod.apply(this, arguments);
|
|
122
|
-
}
|
|
123
|
-
ctx.__mongoose_traced__ = true;
|
|
124
|
-
|
|
125
|
-
const dbc_step = self.createDBCStep(ctx);
|
|
126
|
-
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
127
|
-
ctx.profile.push(dbc_step);
|
|
128
|
-
|
|
129
|
-
// SQL Step 생성
|
|
130
|
-
const sql_step = new SqlStepX();
|
|
131
|
-
sql_step.start_time = ctx.getElapsedTime();
|
|
132
|
-
|
|
133
|
-
const result = originalMethod.apply(this, arguments);
|
|
134
|
-
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
135
|
-
|
|
136
|
-
try {
|
|
137
|
-
const filterObj = arguments[0];
|
|
138
|
-
const parseResult = self.parseSingleFilter(methodName, filterObj);
|
|
54
|
+
// Mongoose 에러 처리
|
|
55
|
+
function handleMongooseError(ctx, err) {
|
|
56
|
+
if (!err) return;
|
|
139
57
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
DataTextAgent.SQL.add(sql_step.hash, sql);
|
|
151
|
-
|
|
152
|
-
// 파라미터 암호화 처리
|
|
153
|
-
if (conf.getProperty('profile_mongodb_param_enabled', false) === true &&
|
|
154
|
-
parseResult.values.length > 0) {
|
|
155
|
-
sql_step.setTrue(1);
|
|
156
|
-
var crc = {value: 0};
|
|
157
|
-
const valuesString = parseResult.values.map(val => {
|
|
158
|
-
if (typeof val === 'string') {
|
|
159
|
-
return `'${val}'`;
|
|
160
|
-
}
|
|
161
|
-
return val;
|
|
162
|
-
}).toString();
|
|
163
|
-
sql_step.p2 = toParamBytes(valuesString, crc);
|
|
164
|
-
sql_step.pcrc = crc.value;
|
|
58
|
+
try {
|
|
59
|
+
var errorClass = err.code || err.name || 'MongooseError';
|
|
60
|
+
var errorMessage = err.message || 'mongoose error';
|
|
61
|
+
var errorStack = '';
|
|
62
|
+
|
|
63
|
+
if (conf.trace_sql_error_stack && conf.trace_sql_error_depth && err.stack) {
|
|
64
|
+
var traceDepth = conf.trace_sql_error_depth;
|
|
65
|
+
var stackLines = err.stack.split("\n");
|
|
66
|
+
if (stackLines.length > traceDepth) {
|
|
67
|
+
stackLines = stackLines.slice(0, traceDepth + 1);
|
|
165
68
|
}
|
|
166
|
-
|
|
167
|
-
ctx.profile.push(sql_step);
|
|
168
|
-
|
|
169
|
-
} catch (e) {
|
|
170
|
-
Logger.printError("WHATAP-611", "Mongodb single filter query error", e, false);
|
|
69
|
+
errorStack = stackLines.join("\n");
|
|
171
70
|
}
|
|
172
71
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return originalMethod.apply(this, arguments);
|
|
72
|
+
var shouldAddError = false;
|
|
73
|
+
if (conf._is_trace_ignore_err_cls_contains === true && errorClass &&
|
|
74
|
+
errorClass.toString().indexOf(conf.trace_ignore_err_cls_contains) < 0) {
|
|
75
|
+
shouldAddError = true;
|
|
76
|
+
} else if (conf._is_trace_ignore_err_msg_contains === true && errorMessage &&
|
|
77
|
+
errorMessage.indexOf(conf.trace_ignore_err_msg_contains) < 0) {
|
|
78
|
+
shouldAddError = true;
|
|
79
|
+
} else if (conf._is_trace_ignore_err_cls_contains === false &&
|
|
80
|
+
conf._is_trace_ignore_err_msg_contains === false) {
|
|
81
|
+
shouldAddError = true;
|
|
184
82
|
}
|
|
185
|
-
ctx.__mongoose_traced__ = true;
|
|
186
|
-
|
|
187
|
-
// DBC Step 생성
|
|
188
|
-
const dbc_step = self.createDBCStep(ctx);
|
|
189
|
-
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
190
|
-
ctx.profile.push(dbc_step);
|
|
191
|
-
|
|
192
|
-
// SQL Step 생성
|
|
193
|
-
const sql_step = new SqlStepX();
|
|
194
|
-
sql_step.start_time = ctx.getElapsedTime();
|
|
195
|
-
|
|
196
|
-
const result = originalMethod.apply(this, arguments);
|
|
197
|
-
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
198
|
-
|
|
199
|
-
try {
|
|
200
|
-
const filterObj = arguments[0];
|
|
201
|
-
const updateObj = arguments[1];
|
|
202
|
-
const parseResult = self.parseDoubleFilter(methodName, filterObj, updateObj);
|
|
203
83
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (parseResult.updateFields.length > 0) {
|
|
213
|
-
sql += ` field=[${parseResult.updateFields.join(',')}]`;
|
|
84
|
+
if (shouldAddError) {
|
|
85
|
+
if (!ctx.error) ctx.error = 1;
|
|
86
|
+
ctx.status = 500;
|
|
87
|
+
var errors = [errorClass];
|
|
88
|
+
if (errorMessage) {
|
|
89
|
+
errors.push(errorMessage);
|
|
214
90
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
sql_step.hash = HashUtil.hashFromString(sql);
|
|
218
|
-
DataTextAgent.SQL.add(sql_step.hash, sql);
|
|
219
|
-
|
|
220
|
-
// 파라미터 암호화 처리 (where 값 + update 값)
|
|
221
|
-
if (conf.getProperty('profile_mongodb_param_enabled', false) === true && parseResult.values.length > 0) {
|
|
222
|
-
sql_step.setTrue(1);
|
|
223
|
-
var crc = {value: 0};
|
|
224
|
-
const valuesString = parseResult.values.map(val => {
|
|
225
|
-
if (typeof val === 'string') {
|
|
226
|
-
return `'${val}'`;
|
|
227
|
-
}
|
|
228
|
-
return val;
|
|
229
|
-
}).toString();
|
|
230
|
-
sql_step.p2 = toParamBytes(valuesString, crc);
|
|
231
|
-
sql_step.pcrc = crc.value;
|
|
91
|
+
if (errorStack || err.stack) {
|
|
92
|
+
errors.push(errorStack || err.stack);
|
|
232
93
|
}
|
|
233
94
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
} catch (e) {
|
|
237
|
-
Logger.printError("WHATAP-611", "Mongodb double filter query error", e, false);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return result;
|
|
241
|
-
};
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
MongooseObserver.prototype.createAggregateWrapper = function(originalAggregate) {
|
|
245
|
-
var self = this;
|
|
246
|
-
|
|
247
|
-
return function wrappedAggregate() {
|
|
248
|
-
const ctx = TraceContextManager.getCurrentContext();
|
|
249
|
-
if (!ctx) {
|
|
250
|
-
return originalAggregate.apply(this, arguments);
|
|
95
|
+
AsyncSender.send_packet(PacketTypeEnum.TX_ERROR, ctx, errors);
|
|
251
96
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
try {
|
|
266
|
-
const pipeline = arguments[0];
|
|
267
|
-
const parseResult = self.parseAggregatePipeline(pipeline);
|
|
268
|
-
|
|
269
|
-
// SQL 문자열 생성
|
|
270
|
-
const modelName = this.modelName || 'Unknown';
|
|
271
|
-
let sql = `${modelName} aggregate`;
|
|
272
|
-
|
|
273
|
-
if (parseResult.matchFields.length > 0) {
|
|
274
|
-
sql += ` where=[${parseResult.matchFields.join(',')}]`;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (parseResult.groupFields.length > 0) {
|
|
278
|
-
sql += ` group=[${parseResult.groupFields.join(',')}]`;
|
|
97
|
+
} catch (e) {
|
|
98
|
+
Logger.printError('WHATAP-245', 'Error handling Mongoose error', e, false);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Model 메서드 래퍼 생성
|
|
103
|
+
function createModelMethodWrapper(methodName) {
|
|
104
|
+
return function(original) {
|
|
105
|
+
return function wrappedMethod() {
|
|
106
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
107
|
+
if (!ctx) {
|
|
108
|
+
return original.apply(this, arguments);
|
|
279
109
|
}
|
|
280
110
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
111
|
+
var args = Array.prototype.slice.call(arguments);
|
|
112
|
+
var modelName = this.modelName || this.collection?.collectionName || 'unknown';
|
|
113
|
+
var commandName = MONGOOSE_COMMANDS[methodName] || methodName.toUpperCase();
|
|
114
|
+
|
|
115
|
+
const asyncResource = new AsyncResource('mongoose-command');
|
|
116
|
+
|
|
117
|
+
return asyncResource.runInAsyncScope(() => {
|
|
118
|
+
// DB 연결 패킷 전송
|
|
119
|
+
ctx.start_time = Date.now();
|
|
120
|
+
ctx.elapsed = 0;
|
|
121
|
+
AsyncSender.send_packet(PacketTypeEnum.TX_DB_CONN, ctx, [dbc]);
|
|
122
|
+
|
|
123
|
+
var command_start_time = Date.now();
|
|
124
|
+
ctx.footprint(`Mongoose ${commandName} Start`);
|
|
125
|
+
|
|
126
|
+
// 쿼리 텍스트 구성
|
|
127
|
+
var queryParts = [commandName, modelName];
|
|
128
|
+
var fieldNames = [];
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
if (methodName === 'aggregate' && Array.isArray(args[0])) {
|
|
132
|
+
// aggregate 파이프라인 처리
|
|
133
|
+
var pipelineFields = [];
|
|
134
|
+
args[0].forEach(function(stage) {
|
|
135
|
+
if (stage.$match) {
|
|
136
|
+
pipelineFields = pipelineFields.concat(Object.keys(stage.$match));
|
|
137
|
+
}
|
|
138
|
+
if (stage.$group) {
|
|
139
|
+
pipelineFields = pipelineFields.concat(Object.keys(stage.$group));
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
if (pipelineFields.length > 0) {
|
|
143
|
+
queryParts.push('field=[' + pipelineFields.join(',') + ']');
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
// 첫 번째 인자에서 필드명 추출
|
|
147
|
+
if (args[0] && typeof args[0] === 'object' && !Array.isArray(args[0])) {
|
|
148
|
+
fieldNames = Object.keys(args[0]);
|
|
149
|
+
}
|
|
150
|
+
if (fieldNames.length > 0) {
|
|
151
|
+
queryParts.push('field=[' + fieldNames.join(',') + ']');
|
|
152
|
+
}
|
|
284
153
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
154
|
+
// 두 번째 인자에서 업데이트 필드 추출 (update 계열 메서드)
|
|
155
|
+
if (args[1] && typeof args[1] === 'object' &&
|
|
156
|
+
(methodName.includes('update') || methodName.includes('Update'))) {
|
|
157
|
+
var updateFields = [];
|
|
158
|
+
if (args[1].$set) {
|
|
159
|
+
updateFields = updateFields.concat(Object.keys(args[1].$set));
|
|
160
|
+
} else {
|
|
161
|
+
updateFields = Object.keys(args[1]);
|
|
162
|
+
}
|
|
163
|
+
if (updateFields.length > 0) {
|
|
164
|
+
queryParts.push('value=[' + updateFields.join(',') + ']');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
297
167
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
sql_step.pcrc = crc.value;
|
|
302
|
-
}
|
|
168
|
+
} catch (e) {
|
|
169
|
+
Logger.printError('WHATAP-246', 'Error extracting field names', e, false);
|
|
170
|
+
}
|
|
303
171
|
|
|
304
|
-
|
|
172
|
+
var commandText = 'MongoDB ' + queryParts.join(' ');
|
|
305
173
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
174
|
+
function executeCallback(err, result) {
|
|
175
|
+
try {
|
|
176
|
+
var command_elapsed = Date.now() - command_start_time;
|
|
309
177
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
178
|
+
if (err) {
|
|
179
|
+
handleMongooseError(ctx, err);
|
|
180
|
+
}
|
|
313
181
|
|
|
314
|
-
|
|
315
|
-
|
|
182
|
+
ctx.elapsed = command_elapsed;
|
|
183
|
+
AsyncSender.send_packet(PacketTypeEnum.TX_SQL, ctx, [dbc, commandText, '0']);
|
|
184
|
+
ctx.footprint(`Mongoose ${commandName} Done`);
|
|
185
|
+
} catch (e) {
|
|
186
|
+
Logger.printError('WHATAP-247', 'Error in Mongoose callback', e, false);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
316
189
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
190
|
+
// 콜백 처리
|
|
191
|
+
var hasCallback = false;
|
|
192
|
+
for (var i = args.length - 1; i >= 0; i--) {
|
|
193
|
+
if (typeof args[i] === 'function') {
|
|
194
|
+
hasCallback = true;
|
|
195
|
+
var originalCallback = args[i];
|
|
196
|
+
|
|
197
|
+
args[i] = asyncResource.bind(function() {
|
|
198
|
+
var callbackArgs = Array.prototype.slice.call(arguments);
|
|
199
|
+
executeCallback(callbackArgs[0], callbackArgs[1]);
|
|
200
|
+
|
|
201
|
+
if (originalCallback && typeof originalCallback === 'function') {
|
|
202
|
+
return originalCallback.apply(this, callbackArgs);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
323
208
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
209
|
+
try {
|
|
210
|
+
var result = original.apply(this, args);
|
|
211
|
+
|
|
212
|
+
// Promise 기반 처리
|
|
213
|
+
if (!hasCallback && result && typeof result.then === 'function') {
|
|
214
|
+
return result.then(function(res) {
|
|
215
|
+
executeCallback(null, res);
|
|
216
|
+
return res;
|
|
217
|
+
}).catch(function(err) {
|
|
218
|
+
executeCallback(err, null);
|
|
219
|
+
throw err;
|
|
220
|
+
});
|
|
221
|
+
}
|
|
327
222
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
223
|
+
// 동기적 결과 처리
|
|
224
|
+
if (!hasCallback) {
|
|
225
|
+
executeCallback(null, result);
|
|
226
|
+
}
|
|
331
227
|
|
|
332
|
-
|
|
333
|
-
|
|
228
|
+
return result;
|
|
229
|
+
} catch (executeError) {
|
|
230
|
+
executeCallback(executeError, null);
|
|
231
|
+
throw executeError;
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
};
|
|
236
|
+
}
|
|
334
237
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
238
|
+
// Connection wrapper 함수
|
|
239
|
+
var createConnectWrapper = function() {
|
|
240
|
+
return function(original) {
|
|
241
|
+
return function wrappedConnect() {
|
|
242
|
+
var args = Array.prototype.slice.call(arguments);
|
|
243
|
+
var connectionString = args[0];
|
|
244
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
338
245
|
|
|
339
|
-
|
|
340
|
-
const modelName = this.modelName || 'Unknown';
|
|
341
|
-
let sql = `${modelName} ${methodName}`;
|
|
246
|
+
setupDbcInfo(connectionString);
|
|
342
247
|
|
|
343
|
-
if (
|
|
344
|
-
|
|
248
|
+
if (!ctx) {
|
|
249
|
+
return original.apply(this, arguments);
|
|
345
250
|
}
|
|
346
251
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
var
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
252
|
+
const connectionResource = new AsyncResource('mongoose-connect');
|
|
253
|
+
|
|
254
|
+
return connectionResource.runInAsyncScope(() => {
|
|
255
|
+
ctx.start_time = Date.now();
|
|
256
|
+
ctx.footprint('Mongoose Connecting Start');
|
|
257
|
+
ctx.db_opening = true;
|
|
258
|
+
|
|
259
|
+
// 콜백 래핑
|
|
260
|
+
for (var i = args.length - 1; i >= 0; i--) {
|
|
261
|
+
if (typeof args[i] === 'function') {
|
|
262
|
+
var originalCallback = args[i];
|
|
263
|
+
args[i] = connectionResource.bind(function() {
|
|
264
|
+
var callbackArgs = Array.prototype.slice.call(arguments);
|
|
265
|
+
var err = callbackArgs[0];
|
|
266
|
+
|
|
267
|
+
if (ctx) {
|
|
268
|
+
ctx.elapsed = Date.now() - ctx.start_time;
|
|
269
|
+
ctx.db_opening = false;
|
|
270
|
+
|
|
271
|
+
if (err) {
|
|
272
|
+
handleMongooseError(ctx, err);
|
|
273
|
+
ctx.footprint('Mongoose Connecting Error');
|
|
274
|
+
} else {
|
|
275
|
+
ctx.footprint('Mongoose Connecting Done');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return originalCallback.apply(this, callbackArgs);
|
|
280
|
+
});
|
|
281
|
+
break;
|
|
359
282
|
}
|
|
360
|
-
|
|
361
|
-
}).toString();
|
|
362
|
-
sql_step.p2 = toParamBytes(valuesString, crc);
|
|
363
|
-
sql_step.pcrc = crc.value;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
ctx.profile.push(sql_step);
|
|
367
|
-
|
|
368
|
-
} catch (e) {
|
|
369
|
-
Logger.printError("WHATAP-611", "Mongodb insert query error", e, false);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
return result;
|
|
373
|
-
};
|
|
374
|
-
};
|
|
375
|
-
|
|
376
|
-
MongooseObserver.prototype.createDBCStep = function(ctx) {
|
|
377
|
-
if (dbc && conn_dbc_hash) {
|
|
378
|
-
DataTextAgent.DBC.add(conn_dbc_hash, dbc);
|
|
379
|
-
DataTextAgent.METHOD.add(conn_dbc_hash, dbc);
|
|
380
|
-
DataTextAgent.ERROR.add(conn_dbc_hash, dbc);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
var dbc_step = new DBCStep();
|
|
384
|
-
dbc_step.hash = conn_dbc_hash;
|
|
385
|
-
dbc_step.start_time = ctx.getElapsedTime();
|
|
283
|
+
}
|
|
386
284
|
|
|
387
|
-
|
|
388
|
-
};
|
|
285
|
+
var result = original.apply(this, args);
|
|
389
286
|
|
|
390
|
-
//
|
|
391
|
-
|
|
392
|
-
|
|
287
|
+
// Promise 기반 처리
|
|
288
|
+
if (result && typeof result.then === 'function') {
|
|
289
|
+
return result.then(connectionResource.bind(function(connection) {
|
|
290
|
+
if (ctx) {
|
|
291
|
+
ctx.elapsed = Date.now() - ctx.start_time;
|
|
292
|
+
ctx.db_opening = false;
|
|
293
|
+
ctx.footprint('Mongoose Connecting Done');
|
|
294
|
+
}
|
|
393
295
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
}
|
|
296
|
+
// 연결 완료 후 Model 래핑
|
|
297
|
+
if (connection && connection.Model) {
|
|
298
|
+
wrapModelMethods(connection.Model);
|
|
299
|
+
}
|
|
399
300
|
|
|
400
|
-
|
|
401
|
-
}
|
|
301
|
+
return connection;
|
|
302
|
+
})).catch(connectionResource.bind(function(err) {
|
|
303
|
+
if (ctx) {
|
|
304
|
+
ctx.elapsed = Date.now() - ctx.start_time;
|
|
305
|
+
ctx.db_opening = false;
|
|
306
|
+
ctx.footprint('Mongoose Connecting Error');
|
|
307
|
+
handleMongooseError(ctx, err);
|
|
308
|
+
}
|
|
309
|
+
throw err;
|
|
310
|
+
}));
|
|
311
|
+
}
|
|
402
312
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
whereFields: [],
|
|
407
|
-
values: []
|
|
313
|
+
return result;
|
|
314
|
+
});
|
|
315
|
+
};
|
|
408
316
|
};
|
|
409
|
-
|
|
410
|
-
if (filterObj && typeof filterObj === 'object') {
|
|
411
|
-
this.extractFieldsAndValues(filterObj, result.whereFields, result.values);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
return result;
|
|
415
317
|
};
|
|
416
318
|
|
|
417
|
-
//
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
};
|
|
319
|
+
// Model 메서드 래핑 함수
|
|
320
|
+
function wrapModelMethods(ModelConstructor) {
|
|
321
|
+
if (ModelConstructor && ModelConstructor.prototype && !ModelConstructor.__whatap_wrapped__) {
|
|
322
|
+
Object.keys(MONGOOSE_COMMANDS).forEach(function(methodName) {
|
|
323
|
+
if (ModelConstructor.prototype[methodName] &&
|
|
324
|
+
!ModelConstructor.prototype[methodName].__whatap_wrapped__) {
|
|
424
325
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
326
|
+
shimmer.wrap(ModelConstructor.prototype, methodName,
|
|
327
|
+
createModelMethodWrapper(methodName));
|
|
328
|
+
ModelConstructor.prototype[methodName].__whatap_wrapped__ = true;
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
ModelConstructor.__whatap_wrapped__ = true;
|
|
332
|
+
Logger.print('WHATAP-MONGOOSE-MODEL', 'Model methods wrapped', false);
|
|
428
333
|
}
|
|
334
|
+
}
|
|
429
335
|
|
|
430
|
-
|
|
431
|
-
if (
|
|
432
|
-
|
|
336
|
+
MongooseObserver.prototype.inject = function(mod, moduleName) {
|
|
337
|
+
if (mod.__whatap_observe__) {
|
|
338
|
+
return;
|
|
433
339
|
}
|
|
340
|
+
mod.__whatap_observe__ = true;
|
|
341
|
+
Logger.initPrint("MongooseObserver");
|
|
434
342
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
// Aggregate pipeline 파싱
|
|
439
|
-
MongooseObserver.prototype.parseAggregatePipeline = function(pipeline) {
|
|
440
|
-
const result = {
|
|
441
|
-
matchFields: [],
|
|
442
|
-
groupFields: [],
|
|
443
|
-
projectFields: [],
|
|
444
|
-
values: []
|
|
445
|
-
};
|
|
446
|
-
|
|
447
|
-
if (Array.isArray(pipeline)) {
|
|
448
|
-
pipeline.forEach(stage => {
|
|
449
|
-
if (stage.$match) {
|
|
450
|
-
this.extractFieldsAndValues(stage.$match, result.matchFields, result.values);
|
|
451
|
-
}
|
|
452
|
-
if (stage.$group) {
|
|
453
|
-
this.extractGroupFields(stage.$group, result.groupFields);
|
|
454
|
-
}
|
|
455
|
-
if (stage.$project) {
|
|
456
|
-
this.extractProjectFields(stage.$project, result.projectFields);
|
|
457
|
-
}
|
|
458
|
-
});
|
|
343
|
+
if (conf.sql_enabled === false) {
|
|
344
|
+
return;
|
|
459
345
|
}
|
|
460
346
|
|
|
461
|
-
|
|
462
|
-
};
|
|
463
|
-
|
|
464
|
-
// Insert documents 파싱
|
|
465
|
-
MongooseObserver.prototype.parseInsertDocuments = function(methodName, docs) {
|
|
466
|
-
const result = {
|
|
467
|
-
insertFields: [],
|
|
468
|
-
values: []
|
|
469
|
-
};
|
|
347
|
+
var self = this;
|
|
470
348
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
}
|
|
476
|
-
} else if (docs && typeof docs === 'object') {
|
|
477
|
-
this.extractFieldsAndValues(docs, result.insertFields, result.values);
|
|
349
|
+
// mongoose.connect 래핑
|
|
350
|
+
if (mod.connect && !mod.connect.__whatap_wrapped__) {
|
|
351
|
+
shimmer.wrap(mod, 'connect', createConnectWrapper());
|
|
352
|
+
mod.connect.__whatap_wrapped__ = true;
|
|
478
353
|
}
|
|
479
354
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
MongooseObserver.prototype.extractFieldsAndValues = function(obj, fieldsArray, valuesArray) {
|
|
485
|
-
if (!obj || typeof obj !== 'object') return;
|
|
486
|
-
|
|
487
|
-
Object.keys(obj).forEach(key => {
|
|
488
|
-
if (key.startsWith('$')) {
|
|
489
|
-
// MongoDB 연산자는 중첩 처리
|
|
490
|
-
if (typeof obj[key] === 'object') {
|
|
491
|
-
this.extractFieldsAndValues(obj[key], fieldsArray, valuesArray);
|
|
492
|
-
} else {
|
|
493
|
-
valuesArray.push(obj[key]);
|
|
494
|
-
}
|
|
495
|
-
} else {
|
|
496
|
-
fieldsArray.push(key);
|
|
497
|
-
if (obj[key] !== null && obj[key] !== undefined) {
|
|
498
|
-
if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
|
|
499
|
-
// 중첩 객체의 값들도 추출
|
|
500
|
-
this.extractNestedValues(obj[key], valuesArray);
|
|
501
|
-
} else {
|
|
502
|
-
valuesArray.push(obj[key]);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
});
|
|
507
|
-
};
|
|
355
|
+
// 기본 Model이 이미 존재하는 경우 래핑
|
|
356
|
+
if (mod.Model) {
|
|
357
|
+
wrapModelMethods(mod.Model);
|
|
358
|
+
}
|
|
508
359
|
|
|
509
|
-
//
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
//
|
|
516
|
-
if (
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
// 다른 연산자들도 필요시 추가
|
|
528
|
-
} else {
|
|
529
|
-
// 직접 업데이트: {name: "new"} 형태
|
|
530
|
-
fieldsArray.push(key);
|
|
531
|
-
if (updateObj[key] !== null && updateObj[key] !== undefined) {
|
|
532
|
-
valuesArray.push(updateObj[key]);
|
|
360
|
+
// mongoose.model() 메서드 래핑 (새로운 모델 생성 시)
|
|
361
|
+
if (mod.model && !mod.model.__whatap_wrapped__) {
|
|
362
|
+
var originalModel = mod.model;
|
|
363
|
+
mod.model = function() {
|
|
364
|
+
var model = originalModel.apply(this, arguments);
|
|
365
|
+
|
|
366
|
+
// 새로 생성된 모델의 메서드들 래핑
|
|
367
|
+
if (model && !model.__whatap_wrapped__) {
|
|
368
|
+
Object.keys(MONGOOSE_COMMANDS).forEach(function(methodName) {
|
|
369
|
+
if (model[methodName] && !model[methodName].__whatap_wrapped__) {
|
|
370
|
+
shimmer.wrap(model, methodName, createModelMethodWrapper(methodName));
|
|
371
|
+
model[methodName].__whatap_wrapped__ = true;
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
model.__whatap_wrapped__ = true;
|
|
533
375
|
}
|
|
534
|
-
}
|
|
535
|
-
});
|
|
536
|
-
};
|
|
537
|
-
|
|
538
|
-
// Group 필드 추출
|
|
539
|
-
MongooseObserver.prototype.extractGroupFields = function(groupObj, fieldsArray) {
|
|
540
|
-
if (!groupObj || typeof groupObj !== 'object') return;
|
|
541
|
-
|
|
542
|
-
Object.keys(groupObj).forEach(key => {
|
|
543
|
-
if (key !== '_id') {
|
|
544
|
-
fieldsArray.push(key);
|
|
545
|
-
}
|
|
546
|
-
});
|
|
547
|
-
};
|
|
548
|
-
|
|
549
|
-
// Project 필드 추출
|
|
550
|
-
MongooseObserver.prototype.extractProjectFields = function(projectObj, fieldsArray) {
|
|
551
|
-
if (!projectObj || typeof projectObj !== 'object') return;
|
|
552
|
-
|
|
553
|
-
Object.keys(projectObj).forEach(key => {
|
|
554
|
-
fieldsArray.push(key);
|
|
555
|
-
});
|
|
556
|
-
};
|
|
557
376
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
if (!obj || typeof obj !== 'object') return;
|
|
377
|
+
return model;
|
|
378
|
+
};
|
|
561
379
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
} else {
|
|
567
|
-
valuesArray.push(value);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
});
|
|
571
|
-
};
|
|
380
|
+
// 기존 속성들 복사
|
|
381
|
+
Object.keys(originalModel).forEach(function(key) {
|
|
382
|
+
mod.model[key] = originalModel[key];
|
|
383
|
+
});
|
|
572
384
|
|
|
573
|
-
|
|
574
|
-
if (p == null || p.length === 0) {
|
|
575
|
-
return null;
|
|
576
|
-
}
|
|
577
|
-
try {
|
|
578
|
-
return ParamSecurity.encrypt(Buffer.from(p, 'utf8'), crc);
|
|
579
|
-
} catch (e) {
|
|
580
|
-
return null;
|
|
385
|
+
mod.model.__whatap_wrapped__ = true;
|
|
581
386
|
}
|
|
582
387
|
};
|
|
583
388
|
|