whatap 0.5.0 → 0.5.2

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.
@@ -8,7 +8,6 @@ var TraceContextManager = require('../trace/trace-context-manager'),
8
8
  ParsedSql = require('../trace/parsed-sql'),
9
9
  SqlStepX = require('../step/sql-stepx'),
10
10
  DBCStep = require('../step/dbc-step'),
11
- ResultSetStep = require('../step/resultset-step'),
12
11
  DataTextAgent = require('../data/datatext-agent'),
13
12
  StatSql = require('../stat/stat-sql'),
14
13
  MeterSql = require('../counter/meter/meter-sql'),
@@ -20,148 +19,228 @@ var TraceContextManager = require('../trace/trace-context-manager'),
20
19
  TextTypes = require('../lang/text-types'),
21
20
  ParamSecurity = require('../util/paramsecurity'),
22
21
  Logger = require('../logger'),
23
- conf = require('../conf/configure'),
24
22
  Buffer = require('buffer').Buffer,
25
- DateUtil = require('../util/dateutil'),
26
- MessageStep = require("../step/message-step");
27
- // const ResourceProfile = require("../util/resourceprofile");
23
+ DateUtil = require('../util/dateutil');
24
+ const shimmer = require('../core/shimmer');
28
25
 
29
26
  var PgSqlObserver = function (agent) {
30
27
  this.agent = agent;
31
28
  this.packages = ['pg'];
32
29
  };
33
30
 
34
- var queryHook = function (dbc_local, agent) {
31
+ var dbc_hash = 0;
32
+ var dbc, dbc_step;
33
+ PgSqlObserver.prototype.inject = function (mod, moduleName) {
34
+ if (mod.__whatap_observe__) { return; }
35
+ mod.__whatap_observe__ = true;
36
+
37
+ Logger.initPrint("PgSqlObserver");
38
+
39
+ var self = this;
40
+ var aop = self.agent.aop;
35
41
 
36
- return function (obj, args) {
42
+ if (conf.sql_enabled === false) { return; }
37
43
 
38
- var ctx = TraceContextManager.getCurrentContext();
44
+ shimmer.wrap(mod.Client.prototype, 'connect', function (original) {
45
+ return function () {
46
+ const ctx = TraceContextManager.getCurrentContext();
47
+ if (!ctx || ctx.db_opening) {
48
+ return original.apply(this, arguments);
49
+ }
39
50
 
40
- if (ctx == null || args[0] == null) { return; }
41
- if(args[0].sql == null && typeof args[0] != 'string') { return; }
51
+ ctx.pg_opening = true;
52
+ ctx.footprint('PgSql Connecting Start');
42
53
 
43
- var sql_step = new SqlStepX();
44
- sql_step.start_time = ctx.getElapsedTime();
45
- ctx.profile.push(sql_step);
46
- ctx.footprint('PgSql Query Start');
54
+ dbc_step = new DBCStep();
55
+ dbc_step.start_time = ctx.getElapsedTime();
47
56
 
48
- ctx.vvv++;
57
+ const finishConnect = function (param) {
58
+ if (ctx) {
59
+ if (dbc_hash === 0) {
60
+ const info = param.connectionParameters;
61
+ dbc = 'postgresql://';
62
+ dbc += (info.user || '') + '@';
63
+ dbc += (info.host || '') + '/';
64
+ dbc += info.database || '';
49
65
 
50
- var sql = args.length > 0 ? args[0] : undefined,
51
- psql = null;
66
+ dbc_hash = HashUtil.hashFromString(dbc);
52
67
 
53
- if(typeof sql !== 'string') {
54
- sql = args[0].sql || undefined;
55
- }
68
+ // DataTextAgent.DBC.add(dbc_hash, dbc);
69
+ // DataTextAgent.METHOD.add(dbc_hash, dbc);
70
+ // DataTextAgent.ERROR.add(dbc_hash, dbc);
71
+ }
72
+ //
73
+ // dbc_step.hash = dbc_hash;
74
+ // dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
75
+ //
76
+ // ctx.db_opening = false;
77
+ // ctx.footprint('PgSql Connecting Done');
78
+ // ctx.profile.push(dbc_step);
79
+ }
80
+ };
56
81
 
57
- if (typeof sql === 'string' && sql.length > 0) {
58
82
  try {
59
- psql = escapeLiteral(sql);
60
- } catch (e) {
61
- Logger.printError('WHATAP-191', 'PgSqlObserver escapeliteral error', e);
83
+ const result = original.apply(this, arguments);
84
+
85
+ if (result && result.then) {
86
+ result.then(finishConnect(this));
87
+ } else {
88
+ finishConnect(this);
89
+ }
90
+
91
+ } catch (err) {
92
+ ctx.db_opening = false;
93
+ Logger.printError('PgSqlObserver', 'Connect Error', err);
94
+ throw err;
62
95
  }
63
- } else {
64
- sql = '';
65
- psql = escapeLiteral(sql);
66
- }
67
-
68
- if(psql != null) {
69
- sql_step.hash = psql.sql;
70
- // = psql.type.charCodeAt(0);
71
- }
72
- sql_step.dbc = dbc_hash;
73
-
74
- var els = new EscapeLiteralSQL(sql);
75
- els.process();
76
-
77
- ctx.active_sqlhash = sql_step.hash;
78
- ctx.active_dbc = sql_step.dbc;
79
- //ctx.active_crud = sql_step.crud;
80
-
81
- if(conf.profile_sql_param_enabled) {
82
- var params = args.length > 1 && Array.isArray(args[1]) ? args[1] : undefined;
83
- sql_step.setTrue(1);
84
- var crc = {value : 0};
85
- sql_step.p1 = toParamBytes(psql.param, crc);
86
- if(params != undefined) {
87
- const result = params.map((param) => {
88
- if(typeof param === 'string'){
89
- return `'${param}'`
90
- }
91
- return param
92
- }).toString()
93
- sql_step.p2 = toParamBytes(result, crc);
96
+ };
97
+ });
98
+
99
+ shimmer.wrap(mod.Client.prototype, 'query', function (original) {
100
+ return function () {
101
+ const ctx = TraceContextManager.getCurrentContext();
102
+ if (!ctx) {
103
+ return original.apply(this, arguments);
94
104
  }
95
- sql_step.pcrc = crc.value;
96
- }
97
105
 
98
- var lastCallback = false;
106
+ if(dbc && dbc_hash){
107
+ if(!dbc_step){
108
+ dbc_step = new DBCStep();
109
+ dbc_step.start_time = ctx.getElapsedTime();
110
+ }
111
+ dbc_step.elapsed = ctx.getElapsedTime() - dbc_step.start_time;
112
+ dbc_step.hash = dbc_hash;
113
+
114
+ DataTextAgent.DBC.add(dbc_hash, dbc);
115
+ DataTextAgent.METHOD.add(dbc_hash, dbc);
116
+ DataTextAgent.ERROR.add(dbc_hash, dbc);
117
+
118
+ ctx.pg_opening = false;
119
+ ctx.footprint('PgSql Connecting Done');
120
+ ctx.profile.push(dbc_step);
121
+ }
122
+ dbc_step = null;
99
123
 
100
- function queryCallback(obj, args) {
124
+ var sql_step = new SqlStepX();
125
+ sql_step.start_time = ctx.getElapsedTime();
126
+ ctx.profile.push(sql_step);
127
+ ctx.footprint('PgSql Query Start');
101
128
 
102
- if (ctx == null) { return; }
103
- TraceContextManager.resume(ctx._id);
129
+ ctx.vvv++;
104
130
 
105
- if (args[0]) {
131
+ let sql = arguments[0];
132
+ let psql = null;
133
+ if (typeof sql === 'string' && sql.length > 0) {
106
134
  try {
107
- if (conf.trace_sql_error_stack && conf.trace_sql_error_depth) {
108
- var traceDepth = conf.trace_sql_error_depth;
135
+ psql = escapeLiteral(sql);
136
+ } catch (e) {
137
+ Logger.printError('WHATAP-191', 'PgSqlObserver escapeliteral error', e);
138
+ }
139
+ } else {
140
+ sql = '';
141
+ psql = escapeLiteral(sql);
142
+ }
109
143
 
110
- var errorStack = args[0].stack.split("\n");
111
- if (errorStack.length > traceDepth) {
112
- errorStack = errorStack.slice(0, traceDepth + 1);
144
+ if(psql != null) {
145
+ sql_step.hash = psql.sql;
146
+ }
147
+ sql_step.dbc = dbc_hash;
148
+
149
+ var els = new EscapeLiteralSQL(sql);
150
+ els.process();
151
+ ctx.active_sqlhash = sql_step.hash;
152
+ ctx.active_dbc = sql_step.dbc;
153
+ //ctx.active_crud = sql_step.crud;
154
+
155
+ if(conf.profile_sql_param_enabled) {
156
+ var params = arguments.length > 1 && Array.isArray(arguments[1]) ? arguments[1] : undefined;
157
+ sql_step.setTrue(1);
158
+ var crc = {value : 0};
159
+ sql_step.p1 = toParamBytes(psql.param, crc);
160
+ if(params != undefined) {
161
+ const result = params.map((param) => {
162
+ if(typeof param === 'string'){
163
+ return `'${param}'`
113
164
  }
114
- var errorStackString = errorStack.join("\n");
115
- var error_stack_step = new MessageStep();
116
- error_stack_step.hash = HashUtil.hashFromString("ERROR STACK");
117
- error_stack_step.start_time = ctx.getElapsedTime();
118
- error_stack_step.desc = errorStackString;
119
- DataTextAgent.MESSAGE.add(error_stack_step.hash, "ERROR STACK");
120
- ctx.profile.push(error_stack_step);
121
- }
122
- if(conf._is_trace_ignore_err_cls_contains === true && args[0].code.indexOf(conf.trace_ignore_err_cls_contains) < 0){
123
- sql_step.error = StatError.addError( 'pgsql-'+args[0].code, args[0].message|| 'pgsql error', ctx.service_hash, TextTypes.SQL, step.hash); /*long*/
124
- if (ctx.error.isZero()) { ctx.error = sql_step.error; }
125
- } else if(conf._is_trace_ignore_err_msg_contains === true && args[0].message.indexOf(conf.trace_ignore_err_msg_contains) < 0){
126
- sql_step.error = StatError.addError( 'pgsql-'+args[0].code, args[0].message|| 'pgsql error', ctx.service_hash, TextTypes.SQL, step.hash); /*long*/
127
- if (ctx.error.isZero()) { ctx.error = sql_step.error; }
128
- } else if(conf._is_trace_ignore_err_cls_contains === false && conf._is_trace_ignore_err_msg_contains === false) {
129
- sql_step.error = StatError.addError( 'pgsql-'+args[0].code, args[0].message|| 'pgsql error', ctx.service_hash, TextTypes.SQL, step.hash); /*long*/
130
- if (ctx.error.isZero()) { ctx.error = sql_step.error; }
131
- }
132
- } catch (e) {
165
+ return param
166
+ }).toString()
167
+ sql_step.p2 = toParamBytes(result, crc);
133
168
  }
169
+ sql_step.pcrc = crc.value;
134
170
  }
135
171
 
136
- sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
137
- ctx.sql_time += sql_step.elapsed;
138
-
139
- // if(conf.getProperty('profile_sql_resource_enabled', false)){
140
- // sql_step.start_cpu = ResourceProfile.getCPUTime();
141
- // sql_step.start_mem = ResourceProfile.getUsedHeapSize();
142
- // }
143
-
144
- ctx.footprint('PgSql Query Done');
145
-
146
- MeterSql.add(dbc_hash, sql_step.elapsed, false);
147
- StatSql.addSqlTime( ctx.service_hash, sql_step.dbc,
148
- sql_step.hash, sql_step.elapsed, args[0] != null, 0);
149
-
150
- if (Array.isArray(args[1]) && psql != null && psql.type === 'S') {
151
- var result_step = new ResultSetStep();
152
- result_step.start_time = ctx.getElapsedTime();
153
- result_step.elapsed = 0;
154
- result_step.fetch = args[1].length;
155
- result_step.sqlhash = psql.sql;
156
- result_step.dbc = dbc_hash;
157
- ctx.profile.push(result_step);
158
- MeterSql.addFetch(result_step.dbc, result_step.fetch, 0);
159
- StatSql.addFetch(result_step.dbc, result_step.sqlhash, result_step.fetch, 0);
172
+ try {
173
+ // SQL 실행
174
+ const result = original.apply(this, arguments);
175
+
176
+ if (result && result.then) {
177
+ return result.then(res => {
178
+ self._finishQuery(ctx, sql_step);
179
+ return res;
180
+ }).catch(err => {
181
+ self._handleError(ctx, sql_step, err)
182
+ if (conf.trace_sql_error_stack && conf.trace_sql_error_depth) {
183
+ var traceDepth = conf.trace_sql_error_depth;
184
+
185
+ var errorStack = err.stack.split("\n");
186
+ if (errorStack.length > traceDepth) {
187
+ errorStack = errorStack.slice(0, traceDepth + 1);
188
+ }
189
+ ctx.error_message = errorStack.join("\n");
190
+ sql_step.error = ctx.error = StatError.addError('pgsql -' + err.code, err.message, ctx.service_hash, TextTypes.SQL, null);
191
+ }
192
+ throw err;
193
+ });
194
+ } else {
195
+ const callback = arguments[arguments.length - 1];
196
+ if (typeof callback === 'function') {
197
+ arguments[arguments.length - 1] = function (err, res) {
198
+ if (err) {
199
+ self._handleError(ctx, sql_step, err);
200
+ } else {
201
+ self._finishQuery(ctx, sql_step);
202
+ }
203
+ return callback.apply(this, arguments);
204
+ };
205
+ }
206
+ return result;
207
+ }
208
+ } catch (err) {
209
+ self._handleError(ctx, sql_step, err);
210
+ throw err;
160
211
  }
161
- }
212
+ };
213
+ });
214
+
215
+ // if (mod.Pool && mod.Pool.prototype.query) {
216
+ // shimmer.wrap(mod.Pool.prototype, 'query', function (original) {
217
+ // return function () {
218
+ // const traceContext = TraceContextManager.getCurrentContext();
219
+ // if (!traceContext) {
220
+ // return original.apply(this, arguments);
221
+ // }
222
+ //
223
+ // // 동일한 방식으로 처리
224
+ // return self.agent.pgClient.query.apply(this, arguments);
225
+ // };
226
+ // });
227
+ // }
228
+ };
162
229
 
163
- lastCallback = agent.aop.functionHook(args, -1, queryCallback);
164
- }
230
+ // 쿼리 완료 처리
231
+ PgSqlObserver.prototype._finishQuery = function (ctx, sql_step) {
232
+ sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
233
+
234
+ MeterSql.add(sql_step.hash, sql_step.elapsed, false);
235
+ StatSql.addSqlTime(ctx, ctx.service_hash, sql_step.dbc, sql_step.hash, sql_step.elapsed, false, 0);
236
+ };
237
+
238
+ PgSqlObserver.prototype._handleError = function (ctx, sql_step, err) {
239
+ sql_step.elapsed = ctx.getElapsedTime() - sql_step.start_time;
240
+
241
+ // Logger.printError('WHATAP-192', 'PGSQL Query error.', err);
242
+ MeterSql.add(sql_step.hash, sql_step.elapsed, false);
243
+ StatSql.addSqlTime(ctx, ctx.service_hash, sql_step.dbc, sql_step.hash, sql_step.elapsed, true, 0);
165
244
  };
166
245
 
167
246
  var toParamBytes = function(p, crc) {
@@ -175,105 +254,6 @@ var toParamBytes = function(p, crc) {
175
254
  }
176
255
  };
177
256
 
178
- var errorDelegate = function () {
179
- return function (obj, args) {
180
-
181
- var ctx = TraceContextManager.getCurrentContext();
182
- if(ctx == null) { return; }
183
-
184
- var laststep = ctx.profile.getLastSteps(1);
185
- if(laststep == null || laststep.length === 0) { return; }
186
-
187
- var step = laststep[0];
188
- if(!args[0].fatal) {
189
- MeterSql.add(step.dbc, step.elapsed, true);
190
- StatSql.addSqlTime(ctx.service_hash, step.dbc, step.hash, step.elapsed, true, 0);
191
- }
192
-
193
- try{
194
- if(args[0].fatal) {
195
- // Connection Error
196
- step.error = StatError.addError("pgsql-"+args[0].code, args[0].message, ctx.service_hash); /*long*/
197
- if (ctx.error.isZero()) { ctx.error = step.error; }
198
- } else {
199
- if(conf._is_trace_ignore_err_cls_contains === true && args[0].code.indexOf(conf.trace_ignore_err_cls_contains) < 0){
200
- step.error = StatError.addError( 'pgsql-'+args[0].code, args[0].message, ctx.service_hash, TextTypes.SQL, step.hash); /*long*/
201
- if (ctx.error.isZero()) { ctx.error = step.error; }
202
- } else if(conf._is_trace_ignore_err_msg_contains === true && args[0].message.indexOf(conf.trace_ignore_err_msg_contains) < 0){
203
- step.error = StatError.addError( 'pgsql-'+args[0].code, args[0].message, ctx.service_hash, TextTypes.SQL, step.hash); /*long*/
204
- if (ctx.error.isZero()) { ctx.error = step.error; }
205
- } else if(conf._is_trace_ignore_err_cls_contains === false && conf._is_trace_ignore_err_msg_contains === false) {
206
- step.error = StatError.addError( 'pgsql-'+args[0].code, args[0].message, ctx.service_hash, TextTypes.SQL, step.hash); /*long*/
207
- if (ctx.error.isZero()) { ctx.error = step.error; }
208
- }
209
- }
210
- } catch(e) {
211
- Logger.printError('WHATAP-997', 'pgsql-observer (errorDelegate)', e, true);
212
- }
213
- }
214
- };
215
-
216
- var dbc_hash=0;
217
- PgSqlObserver.prototype.inject = function (mod, moduleName) {
218
- if(mod.__whatap_observe__) { return; }
219
- mod.__whatap_observe__ = true;
220
-
221
- Logger.initPrint("PgSqlObserver");
222
-
223
- var self = this;
224
- var aop = self.agent.aop;
225
-
226
- if( conf.sql_enabled === false ) { return; }
227
-
228
-
229
- aop.both(mod.Client.prototype, 'connect',
230
- function (obj, args, lctx) {
231
- var ctx = lctx.context;
232
- if(ctx == null || ctx.db_opening) { return; }
233
- ctx.db_opening = true;
234
-
235
- ctx.footprint('PgSql Connecting Start');
236
-
237
- var dbc_step = new DBCStep();
238
- dbc_step.start_time = ctx.getElapsedTime();
239
- lctx.step = dbc_step;
240
- },
241
-
242
- function (obj, args, ret, lctx) {
243
- var pool = ret;
244
- var ctx = lctx.context,
245
- step = lctx.step;
246
-
247
- if(ctx == null || step == null) { return; }
248
- if(dbc_hash === 0){
249
- var dbc;
250
- var info = obj.connectionParameters;
251
- dbc = 'postgresql://';
252
- dbc += info.user || '';
253
- dbc += "@";
254
- dbc += info.host || '';
255
- dbc += '/';
256
- dbc += info.database || '';
257
- dbc_hash = HashUtil.hashFromString(dbc);
258
-
259
- DataTextAgent.DBC.add(dbc_hash, dbc);
260
- DataTextAgent.METHOD.add(dbc_hash, dbc);
261
- DataTextAgent.ERROR.add(dbc_hash, dbc);
262
- }
263
- step.hash=dbc_hash;
264
- step.elapsed = ctx.getElapsedTime() - step.start_time;
265
- ctx.db_opening = false;
266
-
267
- ctx.footprint('PgSql Connecting Done');
268
-
269
- ctx.profile.push(step);
270
-
271
- });
272
- aop.before(mod.Client.prototype, 'query', queryHook(dbc_hash, self.agent));
273
- aop.before(mod.Query.prototype, 'handleError', errorDelegate());
274
-
275
- };
276
-
277
257
  var checkedSql = new IntKeyMap(2000).setMax(2000);
278
258
  var nonLiteSql = new IntKeyMap(5000).setMax(5000);
279
259
  var date = DateUtil.yyyymmdd();
@@ -41,7 +41,6 @@ ProcessObserver.prototype._hookNextTick = function (mod) {
41
41
  ProcessObserver.prototype._hookStdOutWrite = function () {
42
42
  this.agent.aop.after(process.stdout, 'write', (obj, args) => {
43
43
  if (conf.getProperty('logsink_enabled', false) && args[0]) {
44
- return;
45
44
  let content = typeof args[0] === 'string' ? args[0] : (args[0].message || '');
46
45
  try {
47
46
  const parsedContent = JSON.parse(content);
@@ -58,7 +57,6 @@ ProcessObserver.prototype._hookStdOutWrite = function () {
58
57
  ProcessObserver.prototype._hookStdErrWrite = function () {
59
58
  this.agent.aop.after(process.stderr, 'write', (obj, args) => {
60
59
  if (conf.getProperty('logsink_enabled', false) && args[0]) {
61
- return;
62
60
  let content = typeof args[0] === 'string' ? args[0] : (args[0].message || '');
63
61
  try {
64
62
  const parsedContent = JSON.parse(content);
@@ -169,8 +169,13 @@ RedisObserver.prototype.inject = function (mod, modName) {
169
169
  }
170
170
  }
171
171
  }, function (obj, args, ret, lctx) {
172
+ var ctx = lctx.context;
173
+ if (!ctx) {
174
+ return;
175
+ }
176
+
172
177
  var selectCommand = new Set(['get', 'hget', 'hmget', 'zrange', 'smembers', 'lrange']);
173
- var insertCommand = new Set(['set', 'hset', 'hmset', 'zadd', 'lset', 'sadd', 'lpush', 'rpush']);
178
+ var insertCommand = new Set(['set', 'hset', 'hmset', 'zadd', 'lset', 'sadd', 'lpush', 'rpush', 'evalsha']);
174
179
  var updateCommand = new Set(['set', 'lset', 'hset', 'zadd']);
175
180
  var deleteCommand = new Set(['del', 'lrem', 'srem', 'hdel', 'zrem']);
176
181
  var commands = new Set([...selectCommand, ...insertCommand, ...updateCommand, ...deleteCommand]);
@@ -180,10 +185,10 @@ RedisObserver.prototype.inject = function (mod, modName) {
180
185
  }
181
186
  var command = args[0].name;
182
187
  if(commands.has(command.toLowerCase())){
183
- var ctx = TraceContextManager.getCurrentContext();
184
- if (ctx == null) {
185
- return;
186
- }
188
+ // var ctx = TraceContextManager.getCurrentContext();
189
+ // if (ctx == null) {
190
+ // return;
191
+ // }
187
192
 
188
193
  var dbc_step = new DBCStep();
189
194
  dbc_step.hash = ioredis_dbc_hash;