whatap 0.5.20 → 0.5.22
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.
|
@@ -139,7 +139,7 @@ ControlHandler.prototype.handle = async function (p) {
|
|
|
139
139
|
case ParamDef.GET_ENV:
|
|
140
140
|
try {
|
|
141
141
|
var mv = new MapValue();
|
|
142
|
-
let ignore_env_variable = conf.
|
|
142
|
+
let ignore_env_variable = conf.getProperty('ignore_env_variable_set', '');
|
|
143
143
|
let ignore_env_variable_set = ignore_env_variable ? new Set(ignore_env_variable.split(',').map(item => item.trim())) : new Set();
|
|
144
144
|
for (var k in process.env) {
|
|
145
145
|
if(ignore_env_variable_set.has(k)) {
|
|
@@ -779,12 +779,20 @@ HttpObserver.prototype.inject = function( mod, moduleName ) {
|
|
|
779
779
|
});
|
|
780
780
|
});
|
|
781
781
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
782
|
+
shimmer.wrap(mod.Server.prototype, 'emit', function wrapEmit(originalEmit) {
|
|
783
|
+
return function wrappedEmit(eventName, ...args) {
|
|
784
|
+
if (eventName !== 'request') {
|
|
785
|
+
return originalEmit.apply(this, [eventName, ...args]);
|
|
786
|
+
}
|
|
787
|
+
let [req, res] = args;
|
|
788
|
+
return self.__createTransactionObserver(
|
|
789
|
+
(req, res) => originalEmit.call(this, eventName, req, res),
|
|
790
|
+
moduleName === 'https',
|
|
791
|
+
this
|
|
792
|
+
)(req, res);
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
);
|
|
788
796
|
|
|
789
797
|
if( conf.getProperty('httpc_enabled', true) === false ) { return; }
|
|
790
798
|
|
|
@@ -60,6 +60,7 @@ MongoObserver.prototype.inject = function( mod, moduleName ) {
|
|
|
60
60
|
self.agent.aop.before(mod.Collection.prototype, command, function (obj, args) {
|
|
61
61
|
var ctx = TraceContextManager.getCurrentContext();
|
|
62
62
|
if(ctx == null) { return; }
|
|
63
|
+
if(ctx && ctx.__mongoose_traced__) { return; }
|
|
63
64
|
|
|
64
65
|
ctx.footprint('Mongodb Command Start: ' + command );
|
|
65
66
|
var sql_step;
|
|
@@ -94,6 +95,7 @@ MongoObserver.prototype.inject = function( mod, moduleName ) {
|
|
|
94
95
|
self.agent.aop.both(mod.Collection.prototype, command, function (obj, args, lctx) {
|
|
95
96
|
var ctx = lctx.context;
|
|
96
97
|
if(ctx == null) { return; }
|
|
98
|
+
if(ctx && ctx.__mongoose_traced__) { return; }
|
|
97
99
|
|
|
98
100
|
ctx.footprint('Mongodb Command Start: ' + command );
|
|
99
101
|
var sql_step;
|
|
@@ -192,6 +194,7 @@ MongoObserver.prototype.inject = function( mod, moduleName ) {
|
|
|
192
194
|
//args[0] where, args[1] set
|
|
193
195
|
var ctx = TraceContextManager.getCurrentContext();
|
|
194
196
|
if(ctx == null) {return;}
|
|
197
|
+
if(ctx && ctx.__mongoose_traced__) { return; }
|
|
195
198
|
|
|
196
199
|
ctx.footprint('Mongodb Command Start: '+command);
|
|
197
200
|
var sql_step;
|
|
@@ -239,6 +242,7 @@ MongoObserver.prototype.inject = function( mod, moduleName ) {
|
|
|
239
242
|
//args[0] where
|
|
240
243
|
var ctx = TraceContextManager.getCurrentContext();
|
|
241
244
|
if(ctx == null) { return; }
|
|
245
|
+
if(ctx && ctx.__mongoose_traced__) { return; }
|
|
242
246
|
|
|
243
247
|
ctx.footprint('Mongodb Command Start: '+command);
|
|
244
248
|
var sql_step;
|
|
@@ -278,6 +282,7 @@ MongoObserver.prototype.inject = function( mod, moduleName ) {
|
|
|
278
282
|
self.agent.aop.both(mod.Collection.prototype, command, function (obj, args) {
|
|
279
283
|
var ctx = TraceContextManager.getCurrentContext();
|
|
280
284
|
if(ctx == null) { return; }
|
|
285
|
+
if(ctx && ctx.__mongoose_traced__) { return; }
|
|
281
286
|
|
|
282
287
|
ctx.footprint('Mongodb Command Start: '+command);
|
|
283
288
|
var sql_step;
|
|
@@ -4,6 +4,9 @@ var TraceContextManager = require('../trace/trace-context-manager'),
|
|
|
4
4
|
HashUtil = require('../util/hashutil');
|
|
5
5
|
const DBCStep = require("../step/dbc-step");
|
|
6
6
|
const Logger = require("../logger");
|
|
7
|
+
const ParamSecurity = require("../util/paramsecurity");
|
|
8
|
+
const {Buffer} = require("buffer");
|
|
9
|
+
const conf = require('../conf/configure');
|
|
7
10
|
const shimmer = require('../core/shimmer');
|
|
8
11
|
|
|
9
12
|
var MongooseObserver = function (agent) {
|
|
@@ -13,454 +16,569 @@ var MongooseObserver = function (agent) {
|
|
|
13
16
|
|
|
14
17
|
var dbc_step, dbc, conn_dbc_hash;
|
|
15
18
|
|
|
19
|
+
// 단일 필터 메서드 (첫 번째 인자가 filter)
|
|
20
|
+
const collectionMethodsWithFilter = [
|
|
21
|
+
'find',
|
|
22
|
+
// 'findById',
|
|
23
|
+
'findOne',
|
|
24
|
+
'countDocuments',
|
|
25
|
+
'distinct',
|
|
26
|
+
'deleteOne',
|
|
27
|
+
'deleteMany'
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
// 이중 필터 메서드 (첫 번째: filter, 두 번째: update)
|
|
31
|
+
const collectionMethodsWithTwoFilters = [
|
|
32
|
+
'findOneAndUpdate',
|
|
33
|
+
// 'findByIdAndUpdate',
|
|
34
|
+
'updateOne',
|
|
35
|
+
'updateMany',
|
|
36
|
+
'findOneAndDelete',
|
|
37
|
+
// 'findByIdAndDelete',
|
|
38
|
+
'replaceOne'
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
// 특수 메서드
|
|
42
|
+
const specialMethods = [
|
|
43
|
+
'create',
|
|
44
|
+
'insertMany',
|
|
45
|
+
'aggregate'
|
|
46
|
+
];
|
|
47
|
+
|
|
16
48
|
MongooseObserver.prototype.inject = function (mod, modName) {
|
|
17
49
|
var self = this;
|
|
18
|
-
var hookCommand = [
|
|
19
|
-
"create", // Create: Create a new document
|
|
20
|
-
"insertMany", // Create: Create multiple documents at once
|
|
21
|
-
"find", // Read: Find documents that match criteria
|
|
22
|
-
"findById", // Read: Find a document by its ID
|
|
23
|
-
"findOne", // Read: Find the first document that matches criteria
|
|
24
|
-
"countDocuments", // Read: Count the number of documents that match criteria
|
|
25
|
-
"distinct", // Read: Find distinct values for a given field
|
|
26
|
-
"updateMany", // Update: Update multiple documents that match criteria
|
|
27
|
-
"updateOne", // Update: Update a single document that matches criteria
|
|
28
|
-
"replaceOne", // Update: Replace one document with another
|
|
29
|
-
"findOneAndUpdate", // Update: Find the first document that matches criteria and update it
|
|
30
|
-
"findByIdAndUpdate", // Update: Find a document by its ID and update it
|
|
31
|
-
"deleteOne", // Delete: Delete a single document that matches criteria
|
|
32
|
-
"deleteMany", // Delete: Delete multiple documents that match criteria
|
|
33
|
-
"findOneAndDelete", // Delete: Find the first document that matches criteria and delete it
|
|
34
|
-
"findByIdAndDelete" // Delete: Find a document by its ID and delete it
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
// mongoose.connect 함수를 shimmer로 래핑
|
|
38
|
-
shimmer.wrap(mod, 'connect', function(original) {
|
|
39
|
-
return function wrappedConnect() {
|
|
40
|
-
var args = Array.prototype.slice.call(arguments);
|
|
41
|
-
|
|
42
|
-
if(!args[0]) {
|
|
43
|
-
return original.apply(this, arguments);
|
|
44
|
-
}
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
|
|
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);
|
|
48
57
|
}
|
|
58
|
+
return originalConnect.apply(this, arguments);
|
|
59
|
+
};
|
|
60
|
+
});
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
// Model 생성 후킹
|
|
63
|
+
shimmer.wrap(mod, 'model', function(originalModel) {
|
|
64
|
+
return function wrappedModel() {
|
|
65
|
+
const model = originalModel.apply(this, arguments);
|
|
54
66
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
// Model 생성 시점을 intercept하기 위해 mongoose.model을 hook
|
|
58
|
-
self.hookModelCreation(mod);
|
|
67
|
+
// 생성된 Model에 메서드 패치 적용
|
|
68
|
+
self.patchModelMethods(model);
|
|
59
69
|
|
|
60
|
-
|
|
61
|
-
Logger.printError("WHATAP-612", "Mongodb connection error", e, false);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
return result;
|
|
70
|
+
return model;
|
|
65
71
|
};
|
|
66
72
|
});
|
|
67
|
-
|
|
68
|
-
// 이미 생성된 모델들도 처리하기 위해 mongoose.model 함수를 hook
|
|
69
|
-
this.hookModelCreation(mod);
|
|
70
73
|
};
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
MongooseObserver.prototype.patchModelMethods = function(Model) {
|
|
76
|
+
if(Model.__whatap_observe__) {return;}
|
|
77
|
+
Model.__whatap_observe__ = true;
|
|
74
78
|
var self = this;
|
|
75
79
|
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
+
});
|
|
81
88
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
+
});
|
|
86
97
|
|
|
87
|
-
|
|
88
|
-
|
|
98
|
+
// aggregate 메서드 패치
|
|
99
|
+
if (Model.aggregate) {
|
|
100
|
+
shimmer.wrap(Model, 'aggregate', function(originalAggregate) {
|
|
101
|
+
return self.createAggregateWrapper(originalAggregate);
|
|
89
102
|
});
|
|
90
|
-
mongoose._whatapHooked = true;
|
|
91
103
|
}
|
|
92
104
|
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
105
|
+
// create, insertMany 패치
|
|
106
|
+
['create', 'insertMany'].forEach(function(methodName) {
|
|
107
|
+
if (Model[methodName]) {
|
|
108
|
+
shimmer.wrap(Model, methodName, function(originalMethod) {
|
|
109
|
+
return self.createInsertWrapper(originalMethod, methodName);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
98
112
|
});
|
|
99
113
|
};
|
|
100
114
|
|
|
101
|
-
|
|
102
|
-
MongooseObserver.prototype.wrapModelMethods = function(Model) {
|
|
115
|
+
MongooseObserver.prototype.createSingleFilterWrapper = function(originalMethod, methodName) {
|
|
103
116
|
var self = this;
|
|
104
117
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
118
|
+
return function wrappedSingleFilter() {
|
|
119
|
+
const ctx = TraceContextManager.getCurrentContext();
|
|
120
|
+
if (!ctx) {
|
|
121
|
+
return originalMethod.apply(this, arguments);
|
|
122
|
+
}
|
|
123
|
+
ctx.__mongoose_traced__ = true;
|
|
108
124
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return function wrappedAggregate() {
|
|
113
|
-
return self.wrapAggregateExecution(original, this, arguments);
|
|
114
|
-
};
|
|
115
|
-
});
|
|
116
|
-
}
|
|
125
|
+
const dbc_step = self.createDBCStep(ctx);
|
|
126
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
127
|
+
ctx.profile.push(dbc_step);
|
|
117
128
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
"countDocuments", "distinct", "updateMany", "updateOne",
|
|
122
|
-
"replaceOne", "findOneAndUpdate", "findByIdAndUpdate",
|
|
123
|
-
"deleteOne", "deleteMany", "findOneAndDelete", "findByIdAndDelete"
|
|
124
|
-
];
|
|
125
|
-
|
|
126
|
-
hookCommand.forEach(function(methodName) {
|
|
127
|
-
if (typeof Model[methodName] === 'function') {
|
|
128
|
-
shimmer.wrap(Model, methodName, function(original) {
|
|
129
|
-
return function wrappedMethod() {
|
|
130
|
-
return self.wrapMethodExecution(original, this, arguments, methodName);
|
|
131
|
-
};
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
});
|
|
129
|
+
// SQL Step 생성
|
|
130
|
+
const sql_step = new SqlStepX();
|
|
131
|
+
sql_step.start_time = ctx.getElapsedTime();
|
|
135
132
|
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
const result = originalMethod.apply(this, arguments);
|
|
134
|
+
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
138
135
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
var ctx = TraceContextManager.getCurrentContext();
|
|
136
|
+
try {
|
|
137
|
+
const filterObj = arguments[0];
|
|
138
|
+
const parseResult = self.parseSingleFilter(methodName, filterObj);
|
|
143
139
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
140
|
+
// SQL 문자열 생성: "ModelName methodName where=[field1,field2]"
|
|
141
|
+
const modelName = this.modelName || 'Unknown';
|
|
142
|
+
let sql = `${modelName} ${methodName}`;
|
|
147
143
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
DataTextAgent.METHOD.add(conn_dbc_hash, dbc);
|
|
152
|
-
DataTextAgent.ERROR.add(conn_dbc_hash, dbc);
|
|
153
|
-
}
|
|
144
|
+
if (parseResult.whereFields.length > 0) {
|
|
145
|
+
sql += ` where=[${parseResult.whereFields.join(',')}]`;
|
|
146
|
+
}
|
|
154
147
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
148
|
+
// SQL Step 완성
|
|
149
|
+
sql_step.hash = HashUtil.hashFromString(sql);
|
|
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;
|
|
165
|
+
}
|
|
159
166
|
|
|
160
|
-
|
|
161
|
-
var sql_step = new SqlStepX();
|
|
162
|
-
sql_step.start_time = ctx.getElapsedTime();
|
|
167
|
+
ctx.profile.push(sql_step);
|
|
163
168
|
|
|
164
|
-
|
|
165
|
-
|
|
169
|
+
} catch (e) {
|
|
170
|
+
Logger.printError("WHATAP-611", "Mongodb single filter query error", e, false);
|
|
171
|
+
}
|
|
166
172
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
// Query 객체인 경우 exec 메서드를 wrap하여 실행 시점의 에러를 캐치
|
|
172
|
-
if (result && typeof result.exec === 'function') {
|
|
173
|
-
// Query 객체의 exec 메서드를 wrap
|
|
174
|
-
var originalExec = result.exec;
|
|
175
|
-
result.exec = function(callback) {
|
|
176
|
-
var execResult = originalExec.call(this, callback);
|
|
177
|
-
|
|
178
|
-
// Promise 체인에 catch 추가
|
|
179
|
-
if (execResult && typeof execResult.catch === 'function') {
|
|
180
|
-
execResult = execResult.catch(function(error) {
|
|
181
|
-
// 에러 정보를 컨텍스트에 설정
|
|
182
|
-
ctx.error_message = error.message || error.toString();
|
|
183
|
-
ctx.error_class = error.name || error.constructor?.name || 'MongooseAggregateError';
|
|
184
|
-
|
|
185
|
-
// 에러 정보를 DataTextAgent에도 추가
|
|
186
|
-
if (conn_dbc_hash) {
|
|
187
|
-
DataTextAgent.ERROR.add(conn_dbc_hash, ctx.error_message);
|
|
188
|
-
}
|
|
173
|
+
return result;
|
|
174
|
+
};
|
|
175
|
+
};
|
|
189
176
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
});
|
|
193
|
-
}
|
|
177
|
+
MongooseObserver.prototype.createDoubleFilterWrapper = function(originalMethod, methodName) {
|
|
178
|
+
var self = this;
|
|
194
179
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
result.then = function(onResolve, onReject) {
|
|
202
|
-
return originalThen.call(this, onResolve, function(error) {
|
|
203
|
-
// 에러 정보를 컨텍스트에 설정
|
|
204
|
-
ctx.error_message = error.message || error.toString();
|
|
205
|
-
ctx.error_class = error.name || error.constructor?.name || 'MongooseAggregateError';
|
|
206
|
-
|
|
207
|
-
// 에러 정보를 DataTextAgent에도 추가
|
|
208
|
-
if (conn_dbc_hash) {
|
|
209
|
-
DataTextAgent.ERROR.add(conn_dbc_hash, ctx.error_message);
|
|
210
|
-
}
|
|
180
|
+
return function wrappedDoubleFilter() {
|
|
181
|
+
const ctx = TraceContextManager.getCurrentContext();
|
|
182
|
+
if (!ctx) {
|
|
183
|
+
return originalMethod.apply(this, arguments);
|
|
184
|
+
}
|
|
185
|
+
ctx.__mongoose_traced__ = true;
|
|
211
186
|
|
|
212
|
-
|
|
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);
|
|
213
191
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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
|
+
|
|
204
|
+
// SQL 문자열 생성: "ModelName methodName where=[field1] field=[field2,field3]"
|
|
205
|
+
const modelName = this.modelName || 'Unknown';
|
|
206
|
+
let sql = `${modelName} ${methodName}`;
|
|
207
|
+
|
|
208
|
+
if (parseResult.whereFields.length > 0) {
|
|
209
|
+
sql += ` where=[${parseResult.whereFields.join(',')}]`;
|
|
222
210
|
}
|
|
223
|
-
}
|
|
224
211
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
// 에러 정보를 컨텍스트에 설정
|
|
229
|
-
ctx.error_message = error.message || error.toString();
|
|
230
|
-
ctx.error_class = error.name || error.constructor?.name || 'MongooseAggregateError';
|
|
212
|
+
if (parseResult.updateFields.length > 0) {
|
|
213
|
+
sql += ` field=[${parseResult.updateFields.join(',')}]`;
|
|
214
|
+
}
|
|
231
215
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
216
|
+
// SQL Step 완성
|
|
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;
|
|
232
|
+
}
|
|
236
233
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
234
|
+
ctx.profile.push(sql_step);
|
|
235
|
+
|
|
236
|
+
} catch (e) {
|
|
237
|
+
Logger.printError("WHATAP-611", "Mongodb double filter query error", e, false);
|
|
240
238
|
}
|
|
241
239
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
ctx.error_message = error.message || error.toString();
|
|
246
|
-
ctx.error_class = error.name || error.constructor?.name || 'MongooseAggregateError';
|
|
240
|
+
return result;
|
|
241
|
+
};
|
|
242
|
+
};
|
|
247
243
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
DataTextAgent.ERROR.add(conn_dbc_hash, ctx.error_message);
|
|
251
|
-
}
|
|
244
|
+
MongooseObserver.prototype.createAggregateWrapper = function(originalAggregate) {
|
|
245
|
+
var self = this;
|
|
252
246
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
247
|
+
return function wrappedAggregate() {
|
|
248
|
+
const ctx = TraceContextManager.getCurrentContext();
|
|
249
|
+
if (!ctx) {
|
|
250
|
+
return originalAggregate.apply(this, arguments);
|
|
251
|
+
}
|
|
252
|
+
ctx.__mongoose_traced__ = true;
|
|
256
253
|
|
|
257
|
-
|
|
258
|
-
try {
|
|
254
|
+
const dbc_step = self.createDBCStep(ctx);
|
|
259
255
|
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
260
256
|
ctx.profile.push(dbc_step);
|
|
261
257
|
|
|
262
|
-
//
|
|
263
|
-
|
|
264
|
-
ctx.
|
|
258
|
+
// SQL Step 생성
|
|
259
|
+
const sql_step = new SqlStepX();
|
|
260
|
+
sql_step.start_time = ctx.getElapsedTime();
|
|
265
261
|
|
|
266
|
-
|
|
267
|
-
|
|
262
|
+
const result = originalAggregate.apply(this, arguments);
|
|
263
|
+
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
268
264
|
|
|
269
|
-
|
|
270
|
-
|
|
265
|
+
try {
|
|
266
|
+
const pipeline = arguments[0];
|
|
267
|
+
const parseResult = self.parseAggregatePipeline(pipeline);
|
|
271
268
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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(',')}]`;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (parseResult.projectFields.length > 0) {
|
|
282
|
+
sql += ` field=[${parseResult.projectFields.join(',')}]`;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// SQL Step 완성
|
|
286
|
+
sql_step.hash = HashUtil.hashFromString(sql);
|
|
287
|
+
DataTextAgent.SQL.add(sql_step.hash, sql);
|
|
288
|
+
|
|
289
|
+
// 파라미터 암호화 처리 (주로 $match 조건값들)
|
|
290
|
+
if (conf.getProperty('profile_mongodb_param_enabled', false) === true &&
|
|
291
|
+
parseResult.values.length > 0) {
|
|
292
|
+
sql_step.setTrue(1);
|
|
293
|
+
var crc = {value: 0};
|
|
294
|
+
const valuesString = parseResult.values.map(val => {
|
|
295
|
+
if (typeof val === 'string') {
|
|
296
|
+
return `'${val}'`;
|
|
297
|
+
}
|
|
298
|
+
return val;
|
|
299
|
+
}).toString();
|
|
300
|
+
sql_step.p2 = toParamBytes(valuesString, crc);
|
|
301
|
+
sql_step.pcrc = crc.value;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
ctx.profile.push(sql_step);
|
|
305
|
+
|
|
306
|
+
} catch (e) {
|
|
307
|
+
Logger.printError("WHATAP-611", "Mongodb aggregate query error", e, false);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return result;
|
|
311
|
+
};
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
MongooseObserver.prototype.createInsertWrapper = function(originalMethod, methodName) {
|
|
315
|
+
var self = this;
|
|
316
|
+
|
|
317
|
+
return function wrappedInsert() {
|
|
318
|
+
const ctx = TraceContextManager.getCurrentContext();
|
|
319
|
+
if (!ctx) {
|
|
320
|
+
return originalMethod.apply(this, arguments);
|
|
286
321
|
}
|
|
287
|
-
|
|
322
|
+
ctx.__mongoose_traced__ = true;
|
|
288
323
|
|
|
289
|
-
|
|
324
|
+
const dbc_step = self.createDBCStep(ctx);
|
|
325
|
+
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
326
|
+
ctx.profile.push(dbc_step);
|
|
327
|
+
|
|
328
|
+
// SQL Step 생성
|
|
329
|
+
const sql_step = new SqlStepX();
|
|
330
|
+
sql_step.start_time = ctx.getElapsedTime();
|
|
331
|
+
|
|
332
|
+
const result = originalMethod.apply(this, arguments);
|
|
290
333
|
sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
|
|
291
|
-
DataTextAgent.SQL.add(sql_step.hash, sql);
|
|
292
|
-
ctx.profile.push(sql_step);
|
|
293
334
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
335
|
+
try {
|
|
336
|
+
const docs = arguments[0];
|
|
337
|
+
const parseResult = self.parseInsertDocuments(methodName, docs);
|
|
297
338
|
|
|
298
|
-
|
|
299
|
-
|
|
339
|
+
// SQL 문자열 생성
|
|
340
|
+
const modelName = this.modelName || 'Unknown';
|
|
341
|
+
let sql = `${modelName} ${methodName}`;
|
|
300
342
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
343
|
+
if (parseResult.insertFields.length > 0) {
|
|
344
|
+
sql += ` field=[${parseResult.insertFields.join(',')}]`;
|
|
345
|
+
}
|
|
304
346
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
347
|
+
// SQL Step 완성
|
|
348
|
+
sql_step.hash = HashUtil.hashFromString(sql);
|
|
349
|
+
DataTextAgent.SQL.add(sql_step.hash, sql);
|
|
350
|
+
|
|
351
|
+
// 파라미터 암호화 처리
|
|
352
|
+
if (conf.getProperty('profile_mongodb_param_enabled', false) === true &&
|
|
353
|
+
parseResult.values.length > 0) {
|
|
354
|
+
sql_step.setTrue(1);
|
|
355
|
+
var crc = {value: 0};
|
|
356
|
+
const valuesString = parseResult.values.map(val => {
|
|
357
|
+
if (typeof val === 'string') {
|
|
358
|
+
return `'${val}'`;
|
|
359
|
+
}
|
|
360
|
+
return val;
|
|
361
|
+
}).toString();
|
|
362
|
+
sql_step.p2 = toParamBytes(valuesString, crc);
|
|
363
|
+
sql_step.pcrc = crc.value;
|
|
364
|
+
}
|
|
310
365
|
|
|
311
|
-
|
|
312
|
-
if(!ctx) {
|
|
313
|
-
return original.apply(thisArg, argsArray);
|
|
314
|
-
}
|
|
366
|
+
ctx.profile.push(sql_step);
|
|
315
367
|
|
|
316
|
-
|
|
317
|
-
|
|
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) {
|
|
318
378
|
DataTextAgent.DBC.add(conn_dbc_hash, dbc);
|
|
319
379
|
DataTextAgent.METHOD.add(conn_dbc_hash, dbc);
|
|
320
380
|
DataTextAgent.ERROR.add(conn_dbc_hash, dbc);
|
|
321
381
|
}
|
|
322
382
|
|
|
323
|
-
// DBC Step 생성
|
|
324
383
|
var dbc_step = new DBCStep();
|
|
325
384
|
dbc_step.hash = conn_dbc_hash;
|
|
326
385
|
dbc_step.start_time = ctx.getElapsedTime();
|
|
327
386
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
sql_step.start_time = ctx.getElapsedTime();
|
|
387
|
+
return dbc_step;
|
|
388
|
+
};
|
|
331
389
|
|
|
332
|
-
|
|
333
|
-
|
|
390
|
+
// 비동기 결과 처리
|
|
391
|
+
MongooseObserver.prototype.handleAsyncResult = function(result, ctx, methodName) {
|
|
392
|
+
ctx.footprint('Mongodb Command Start: ' + methodName);
|
|
334
393
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if (result && typeof result.exec === 'function') {
|
|
341
|
-
// Query 객체의 exec 메서드를 wrap
|
|
342
|
-
var originalExec = result.exec;
|
|
343
|
-
result.exec = function(callback) {
|
|
344
|
-
var execResult = originalExec.call(this, callback);
|
|
345
|
-
|
|
346
|
-
// Promise 체인에 catch 추가
|
|
347
|
-
if (execResult && typeof execResult.catch === 'function') {
|
|
348
|
-
execResult = execResult.catch(function(error) {
|
|
349
|
-
// 에러 정보를 컨텍스트에 설정
|
|
350
|
-
ctx.error_message = error.message || error.toString();
|
|
351
|
-
ctx.error_class = error.name || error.constructor?.name || 'MongooseError';
|
|
352
|
-
|
|
353
|
-
// 에러 정보를 DataTextAgent에도 추가
|
|
354
|
-
if (conn_dbc_hash) {
|
|
355
|
-
DataTextAgent.ERROR.add(conn_dbc_hash, ctx.error_message);
|
|
356
|
-
}
|
|
394
|
+
// Promise인 경우 처리 (대부분의 Mongoose 메서드가 Promise 반환)
|
|
395
|
+
if (result && typeof result.then === 'function') {
|
|
396
|
+
// 이미 실행은 완료되었으므로 특별한 처리 불필요
|
|
397
|
+
return result;
|
|
398
|
+
}
|
|
357
399
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
});
|
|
361
|
-
}
|
|
400
|
+
return result;
|
|
401
|
+
};
|
|
362
402
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
result.then = function(onResolve, onReject) {
|
|
370
|
-
return originalThen.call(this, onResolve, function(error) {
|
|
371
|
-
// 에러 정보를 컨텍스트에 설정
|
|
372
|
-
ctx.error_message = error.message || error.toString();
|
|
373
|
-
ctx.error_class = error.name || error.constructor?.name || 'MongooseError';
|
|
374
|
-
|
|
375
|
-
// 에러 정보를 DataTextAgent에도 추가
|
|
376
|
-
if (conn_dbc_hash) {
|
|
377
|
-
DataTextAgent.ERROR.add(conn_dbc_hash, ctx.error_message);
|
|
378
|
-
}
|
|
403
|
+
// 단일 필터 파싱
|
|
404
|
+
MongooseObserver.prototype.parseSingleFilter = function(methodName, filterObj) {
|
|
405
|
+
const result = {
|
|
406
|
+
whereFields: [],
|
|
407
|
+
values: []
|
|
408
|
+
};
|
|
379
409
|
|
|
380
|
-
|
|
410
|
+
if (filterObj && typeof filterObj === 'object') {
|
|
411
|
+
this.extractFieldsAndValues(filterObj, result.whereFields, result.values);
|
|
412
|
+
}
|
|
381
413
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
return onReject(error);
|
|
385
|
-
} else {
|
|
386
|
-
throw error;
|
|
387
|
-
}
|
|
388
|
-
});
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
} else if (result && typeof result.then === 'function') {
|
|
392
|
-
// Promise인 경우 에러 처리를 위해 catch 추가 (직접 Promise를 반환하는 경우)
|
|
393
|
-
result = result.catch(function(error) {
|
|
394
|
-
// 에러 정보를 컨텍스트에 설정
|
|
395
|
-
ctx.error_message = error.message || error.toString();
|
|
396
|
-
ctx.error_class = error.name || error.constructor?.name || 'MongooseError';
|
|
397
|
-
|
|
398
|
-
// 에러 정보를 DataTextAgent에도 추가
|
|
399
|
-
if (conn_dbc_hash) {
|
|
400
|
-
DataTextAgent.ERROR.add(conn_dbc_hash, ctx.error_message);
|
|
401
|
-
}
|
|
414
|
+
return result;
|
|
415
|
+
};
|
|
402
416
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
417
|
+
// 이중 필터 파싱 - 수정된 버전
|
|
418
|
+
MongooseObserver.prototype.parseDoubleFilter = function(methodName, filterObj, updateObj) {
|
|
419
|
+
const result = {
|
|
420
|
+
whereFields: [],
|
|
421
|
+
updateFields: [],
|
|
422
|
+
values: []
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// where 조건 파싱
|
|
426
|
+
if (filterObj && typeof filterObj === 'object') {
|
|
427
|
+
this.extractFieldsAndValues(filterObj, result.whereFields, result.values);
|
|
428
|
+
}
|
|
407
429
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
ctx.error_class = error.name || error.constructor?.name || 'MongooseError';
|
|
430
|
+
// update 조건 파싱 - 수정된 로직
|
|
431
|
+
if (updateObj && typeof updateObj === 'object') {
|
|
432
|
+
this.extractUpdateFieldsOnly(updateObj, result.updateFields, result.values);
|
|
433
|
+
}
|
|
413
434
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
DataTextAgent.ERROR.add(conn_dbc_hash, ctx.error_message);
|
|
417
|
-
}
|
|
435
|
+
return result;
|
|
436
|
+
};
|
|
418
437
|
|
|
419
|
-
|
|
420
|
-
|
|
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
|
+
});
|
|
421
459
|
}
|
|
422
460
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
|
|
426
|
-
ctx.profile.push(dbc_step);
|
|
427
|
-
|
|
428
|
-
// operation 이름 가져오기
|
|
429
|
-
var operation = (result && result.op) ? result.op : methodName;
|
|
430
|
-
ctx.footprint('Mongodb Command Start: ' + operation);
|
|
461
|
+
return result;
|
|
462
|
+
};
|
|
431
463
|
|
|
432
|
-
|
|
433
|
-
|
|
464
|
+
// Insert documents 파싱
|
|
465
|
+
MongooseObserver.prototype.parseInsertDocuments = function(methodName, docs) {
|
|
466
|
+
const result = {
|
|
467
|
+
insertFields: [],
|
|
468
|
+
values: []
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
if (methodName === 'insertMany' && Array.isArray(docs)) {
|
|
472
|
+
// 첫 번째 문서의 필드들을 기준으로 함
|
|
473
|
+
if (docs.length > 0 && typeof docs[0] === 'object') {
|
|
474
|
+
this.extractFieldsAndValues(docs[0], result.insertFields, result.values);
|
|
475
|
+
}
|
|
476
|
+
} else if (docs && typeof docs === 'object') {
|
|
477
|
+
this.extractFieldsAndValues(docs, result.insertFields, result.values);
|
|
478
|
+
}
|
|
434
479
|
|
|
435
|
-
|
|
480
|
+
return result;
|
|
481
|
+
};
|
|
436
482
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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
|
+
}
|
|
443
504
|
}
|
|
444
505
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
506
|
+
});
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
// Update 필드만 추출 (수정된 버전) - where 필드 중복 방지
|
|
510
|
+
MongooseObserver.prototype.extractUpdateFieldsOnly = function(updateObj, fieldsArray, valuesArray) {
|
|
511
|
+
if (!updateObj || typeof updateObj !== 'object') return;
|
|
512
|
+
|
|
513
|
+
Object.keys(updateObj).forEach(key => {
|
|
514
|
+
if (key.startsWith('$')) {
|
|
515
|
+
// $set: {name: 'new', email: 'new'} 처리
|
|
516
|
+
if (key === '$set' || key === '$inc' || key === '$push' || key === '$pull' || key === '$unset') {
|
|
517
|
+
if (typeof updateObj[key] === 'object') {
|
|
518
|
+
Object.keys(updateObj[key]).forEach(field => {
|
|
519
|
+
fieldsArray.push(field);
|
|
520
|
+
const value = updateObj[key][field];
|
|
521
|
+
if (value !== null && value !== undefined) {
|
|
522
|
+
valuesArray.push(value);
|
|
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]);
|
|
451
533
|
}
|
|
452
534
|
}
|
|
535
|
+
});
|
|
536
|
+
};
|
|
453
537
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
ctx.profile.push(sql_step);
|
|
538
|
+
// Group 필드 추출
|
|
539
|
+
MongooseObserver.prototype.extractGroupFields = function(groupObj, fieldsArray) {
|
|
540
|
+
if (!groupObj || typeof groupObj !== 'object') return;
|
|
458
541
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
542
|
+
Object.keys(groupObj).forEach(key => {
|
|
543
|
+
if (key !== '_id') {
|
|
544
|
+
fieldsArray.push(key);
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
};
|
|
462
548
|
|
|
463
|
-
|
|
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
|
+
|
|
558
|
+
// 중첩 값 추출
|
|
559
|
+
MongooseObserver.prototype.extractNestedValues = function(obj, valuesArray) {
|
|
560
|
+
if (!obj || typeof obj !== 'object') return;
|
|
561
|
+
|
|
562
|
+
Object.values(obj).forEach(value => {
|
|
563
|
+
if (value !== null && value !== undefined) {
|
|
564
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
565
|
+
this.extractNestedValues(value, valuesArray);
|
|
566
|
+
} else {
|
|
567
|
+
valuesArray.push(value);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
var toParamBytes = function (p, crc) {
|
|
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;
|
|
581
|
+
}
|
|
464
582
|
};
|
|
465
583
|
|
|
466
584
|
exports.MongooseObserver = MongooseObserver;
|
package/package.json
CHANGED