whatap 0.5.7 → 0.5.8
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.
|
@@ -267,7 +267,11 @@ var ConfigDefault = {
|
|
|
267
267
|
"grpc_profile_ignore_method": bool("grpc_profile_ignore_method", true),
|
|
268
268
|
|
|
269
269
|
"oname_port_postfix_enabled": bool("oname_port_postfix_enabled", false),
|
|
270
|
-
"ignore_http_lost_connection": bool("ignore_http_lost_connection", false)
|
|
270
|
+
"ignore_http_lost_connection": bool("ignore_http_lost_connection", false),
|
|
271
|
+
|
|
272
|
+
"profile_graphql_enabled": bool("profile_graphql_enabled", true),
|
|
273
|
+
"profile_graphql_variable_enabled": bool("profile_graphql_variable_enabled", false),
|
|
274
|
+
"ignore_graphql_operation": str("ignore_graphql_operation", '')
|
|
271
275
|
};
|
|
272
276
|
|
|
273
277
|
ConfigDefault._hook_method_ignore_prefix = ConfigDefault.hook_method_ignore_prefixes.split(',');
|
package/lib/core/agent.js
CHANGED
|
@@ -30,7 +30,9 @@ var Interceptor = require('./interceptor').Interceptor,
|
|
|
30
30
|
PromiseObserver = require('../observers/promise-observer').PromiseObserver,
|
|
31
31
|
PgSqlObserver = require('../observers/pgsql-observer').PgSqlObserver,
|
|
32
32
|
ScheduleObserver = require('../observers/schedule-observer').ScheduleObserver,
|
|
33
|
-
GRpcObserver = require('../observers/grpc-observer').GRpcObserver
|
|
33
|
+
GRpcObserver = require('../observers/grpc-observer').GRpcObserver,
|
|
34
|
+
ApolloObserver = require('../observers/apollo-server-observer').ApolloServerObserver;
|
|
35
|
+
|
|
34
36
|
|
|
35
37
|
var Configuration = require('./../conf/configure'),
|
|
36
38
|
SecurityMaster = require('./../net/security-master'),
|
|
@@ -268,6 +270,7 @@ NodeAgent.prototype.loadObserves = function() {
|
|
|
268
270
|
observes.push(PgSqlObserver);
|
|
269
271
|
observes.push(ScheduleObserver);
|
|
270
272
|
// observes.push(GRpcObserver);
|
|
273
|
+
observes.push(ApolloObserver);
|
|
271
274
|
|
|
272
275
|
var packageToObserve = {};
|
|
273
276
|
observes.forEach(function(observeObj) {
|
|
@@ -0,0 +1,155 @@
|
|
|
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
|
+
|
|
7
|
+
var TraceContextManager = require('../trace/trace-context-manager'),
|
|
8
|
+
conf = require('../conf/configure'),
|
|
9
|
+
Logger = require('../logger');
|
|
10
|
+
const HashUtil = require('../util/hashutil');
|
|
11
|
+
const DataTextAgent = require('../data/datatext-agent');
|
|
12
|
+
const MessageStep = require('../step/message-step');
|
|
13
|
+
const shimmer = require('../core/shimmer');
|
|
14
|
+
const StatError = require("../stat/stat-error");
|
|
15
|
+
const TextTypes = require("../lang/text-types");
|
|
16
|
+
|
|
17
|
+
var profile_graphql_enabled = conf.getProperty('profile_graphql_enabled', true);
|
|
18
|
+
var profile_graphql_variable_enabled = conf.getProperty('profile_graphql_variable_enabled', false);
|
|
19
|
+
var ignore_graphql_operation = conf.getProperty('ignore_graphql_operation', '');
|
|
20
|
+
|
|
21
|
+
conf.on('profile_graphql_enabled', function(newProperty) {
|
|
22
|
+
profile_graphql_enabled = newProperty;
|
|
23
|
+
});
|
|
24
|
+
conf.on('profile_graphql_variable_enabled', function(newProperty) {
|
|
25
|
+
profile_graphql_variable_enabled = newProperty;
|
|
26
|
+
});
|
|
27
|
+
conf.on('ignore_graphql_operation', function(newProperty) {
|
|
28
|
+
ignore_graphql_operation = newProperty;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
var ApolloServerObserver = function(agent) {
|
|
32
|
+
this.agent = agent;
|
|
33
|
+
this.packages = ['@apollo/server'];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function checkIgnoreOperation(ignore_operation, operation_name) {
|
|
37
|
+
try {
|
|
38
|
+
let ignore_operation_set = null;
|
|
39
|
+
if (ignore_operation) {
|
|
40
|
+
ignore_operation_set = new Set(ignore_operation.split(','));
|
|
41
|
+
} else {
|
|
42
|
+
ignore_operation_set = null;
|
|
43
|
+
}
|
|
44
|
+
if (ignore_operation_set && ignore_operation_set.has(operation_name)) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
} catch (e) {
|
|
48
|
+
Logger.printError('WHATAP-803', 'GraphQL checkIgnoreOperation error: ' + e, false);
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function wrapExecuteHTTPGraphQLRequest(original) {
|
|
54
|
+
return async function executeHTTPGraphQLRequest() {
|
|
55
|
+
if (!profile_graphql_enabled) {
|
|
56
|
+
return original.apply(this, arguments);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
var ctx = TraceContextManager.getCurrentContext();
|
|
61
|
+
if (!ctx) {
|
|
62
|
+
return original.apply(this, arguments);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const [requestContext] = arguments;
|
|
66
|
+
const { httpGraphQLRequest } = requestContext;
|
|
67
|
+
const { body } = httpGraphQLRequest;
|
|
68
|
+
|
|
69
|
+
const operationName = body.operationName;
|
|
70
|
+
if (checkIgnoreOperation(ignore_graphql_operation, operationName)) {
|
|
71
|
+
TraceContextManager.end(ctx._id)
|
|
72
|
+
return original.apply(this, arguments);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const originalServiceName = ctx.service_name || '';
|
|
76
|
+
if(operationName){
|
|
77
|
+
ctx.service_name = `${originalServiceName}?operationName=${operationName}`;
|
|
78
|
+
ctx.service_hash = HashUtil.hashFromString(ctx.service_name);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Operation Type Step (query)
|
|
82
|
+
if(body.query && body.query.trim()){
|
|
83
|
+
var step_type = new MessageStep();
|
|
84
|
+
step_type.hash = HashUtil.hashFromString('Type');
|
|
85
|
+
step_type.start_time = ctx.getElapsedTime();
|
|
86
|
+
step_type.desc = body.query.trim().startsWith('mutation') ? 'mutation' : 'query';
|
|
87
|
+
DataTextAgent.MESSAGE.add(step_type.hash, "Type");
|
|
88
|
+
ctx.profile.push(step_type);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Operation Name Step
|
|
92
|
+
if(operationName){
|
|
93
|
+
var step_operation = new MessageStep();
|
|
94
|
+
step_operation.hash = HashUtil.hashFromString('Operation');
|
|
95
|
+
step_operation.start_time = ctx.getElapsedTime();
|
|
96
|
+
step_operation.desc = operationName || 'anonymous';
|
|
97
|
+
DataTextAgent.MESSAGE.add(step_operation.hash, "Operation");
|
|
98
|
+
ctx.profile.push(step_operation);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Variables Step
|
|
102
|
+
if (profile_graphql_variable_enabled && body.variables && Object.keys(body.variables).length > 0) {
|
|
103
|
+
var step_variables = new MessageStep();
|
|
104
|
+
step_variables.hash = HashUtil.hashFromString('Variables');
|
|
105
|
+
step_variables.start_time = ctx.getElapsedTime();
|
|
106
|
+
step_variables.desc = JSON.stringify(Object.keys(body.variables));
|
|
107
|
+
DataTextAgent.MESSAGE.add(step_variables.hash, "Variables");
|
|
108
|
+
ctx.profile.push(step_variables);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const response = await original.apply(this, arguments);
|
|
112
|
+
|
|
113
|
+
// 에러 처리
|
|
114
|
+
if (response.body.kind === 'complete' && response.body.string.includes('"errors"')) {
|
|
115
|
+
try {
|
|
116
|
+
const result = JSON.parse(response.body.string);
|
|
117
|
+
if (result.errors && result.errors.length > 0) {
|
|
118
|
+
const errorMessages = result.errors.map(error => error.message).join('\n');
|
|
119
|
+
ctx.statusCode = 500;
|
|
120
|
+
ctx.error_message = errorMessages;
|
|
121
|
+
}
|
|
122
|
+
} catch (e) {
|
|
123
|
+
Logger.printError('WHATAP-802', 'GraphQL error parsing failed', e, false);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return response;
|
|
128
|
+
|
|
129
|
+
} catch (err) {
|
|
130
|
+
Logger.printError('WHATAP-801', 'GraphQL executeHTTPGraphQLRequest error: ' + err, false);
|
|
131
|
+
if (ctx) {
|
|
132
|
+
ctx.statusCode = 500;
|
|
133
|
+
ctx.error_message = err.stack;
|
|
134
|
+
}
|
|
135
|
+
return original.apply(this, arguments);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
ApolloServerObserver.prototype.inject = function(mod, moduleName) {
|
|
141
|
+
if (mod.__whatap_observe__) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
mod.__whatap_observe__ = true;
|
|
145
|
+
Logger.initPrint("ApolloServerObserver");
|
|
146
|
+
|
|
147
|
+
if (profile_graphql_enabled) {
|
|
148
|
+
// Hook ApolloServer
|
|
149
|
+
if (mod.ApolloServer && mod.ApolloServer.prototype) {
|
|
150
|
+
shimmer.wrap(mod.ApolloServer.prototype, 'executeHTTPGraphQLRequest', wrapExecuteHTTPGraphQLRequest);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
exports.ApolloServerObserver = ApolloServerObserver;
|
package/package.json
CHANGED