@sentienguard/apm 1.0.5 → 1.0.7

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/src/config.js CHANGED
@@ -2,87 +2,93 @@
2
2
  * SDK Configuration
3
3
  * Environment-driven configuration with sensible defaults.
4
4
  * No config → SDK disables itself silently.
5
+ *
6
+ * Config is loaded lazily (at initialize() time, not import time)
7
+ * so that dotenv or other env loaders can run first.
5
8
  */
6
9
 
7
- const config = {
8
- // API key for authentication (required)
9
- apiKey: process.env.SENTIENGUARD_APM_KEY || '',
10
-
11
- // Service name (required for data to be meaningful)
12
- service: process.env.SENTIENGUARD_SERVICE || '',
13
-
14
- // Environment (production, staging, development)
15
- environment: process.env.SENTIENGUARD_ENV || 'production',
16
-
17
- // Backend endpoint for data ingestion
18
- // Production: https://sentienguard-dev.the-algo.com/api/v1/apm/ingest
19
- // Local: http://localhost:4000/api/v1/apm/ingest
20
- endpoint: process.env.SENTIENGUARD_ENDPOINT || 'https://sentienguard-dev.the-algo.com/api/v1/apm/ingest',
21
-
22
- // Flush interval in seconds (default: 10s)
23
- flushInterval: parseInt(process.env.SENTIENGUARD_FLUSH_INTERVAL, 10) || 10,
24
-
25
- // Max unique routes to track per service (prevents memory bloat)
26
- maxRoutes: parseInt(process.env.SENTIENGUARD_MAX_ROUTES, 10) || 100,
27
-
28
- // Max payload size in bytes (prevent oversized payloads)
29
- maxPayloadSize: parseInt(process.env.SENTIENGUARD_MAX_PAYLOAD_SIZE, 10) || 1024 * 1024, // 1MB
30
-
31
- // Enable/disable SDK (auto-disabled if no API key)
32
- enabled: process.env.SENTIENGUARD_ENABLED !== 'false',
10
+ let configLoaded = false;
33
11
 
34
- // Debug mode (logs SDK activity)
35
- debug: process.env.SENTIENGUARD_DEBUG === 'true',
36
-
37
- // MongoDB monitoring configuration
12
+ const config = {
13
+ apiKey: '',
14
+ service: '',
15
+ environment: 'production',
16
+ endpoint: 'https://sentienguard-dev.the-algo.com/api/v1/apm/ingest',
17
+ flushInterval: 10,
18
+ maxRoutes: 100,
19
+ maxPayloadSize: 1024 * 1024,
20
+ enabled: true,
21
+ debug: false,
38
22
  mongodb: {
39
- // Enable/disable MongoDB instrumentation (default: true)
40
- enabled: process.env.SENTIENGUARD_MONGODB_ENABLED !== 'false',
41
- // Slow query threshold in milliseconds (default: 100ms)
42
- slowQueryMs: parseInt(process.env.SENTIENGUARD_MONGODB_SLOW_QUERY_MS, 10) || 100,
43
- // Interval for collecting pool stats in milliseconds (default: 10s)
44
- poolStatsInterval: parseInt(process.env.SENTIENGUARD_MONGODB_POOL_INTERVAL, 10) || 10000
23
+ enabled: true,
24
+ slowQueryMs: 100,
25
+ poolStatsInterval: 10000
45
26
  },
46
-
47
- // Circuit breaker configuration
48
27
  circuitBreaker: {
49
- // Enable/disable circuit breaker (default: false - opt-in)
50
- enabled: process.env.SENTIENGUARD_CIRCUIT_BREAKER_ENABLED === 'true',
51
- // Timeout for operations in milliseconds (default: 3s)
52
- timeout: parseInt(process.env.SENTIENGUARD_CIRCUIT_TIMEOUT_MS, 10) || 3000,
53
- // Error threshold percentage to trip circuit (default: 50%)
54
- errorThresholdPercentage: parseInt(process.env.SENTIENGUARD_CIRCUIT_ERROR_THRESHOLD, 10) || 50,
55
- // Time to wait before attempting recovery in milliseconds (default: 30s)
56
- resetTimeout: parseInt(process.env.SENTIENGUARD_CIRCUIT_RESET_TIMEOUT, 10) || 30000,
57
- // Minimum requests before calculating error percentage (default: 5)
58
- volumeThreshold: parseInt(process.env.SENTIENGUARD_CIRCUIT_VOLUME_THRESHOLD, 10) || 5
28
+ enabled: false,
29
+ timeout: 3000,
30
+ errorThresholdPercentage: 50,
31
+ resetTimeout: 30000,
32
+ volumeThreshold: 5
59
33
  },
60
-
61
- // OpenAI monitoring configuration
62
34
  openai: {
63
- // Enable/disable OpenAI instrumentation (default: true)
64
- enabled: process.env.SENTIENGUARD_OPENAI_ENABLED !== 'false',
65
- // Track token usage (default: true)
66
- trackTokens: process.env.SENTIENGUARD_OPENAI_TRACK_TOKENS !== 'false',
67
- // Track estimated costs (default: true)
68
- trackCosts: process.env.SENTIENGUARD_OPENAI_TRACK_COSTS !== 'false',
69
- // Slow API call threshold in milliseconds (default: 5000ms / 5s)
70
- slowCallMs: parseInt(process.env.SENTIENGUARD_OPENAI_SLOW_CALL_MS, 10) || 5000
35
+ enabled: true,
36
+ trackTokens: true,
37
+ trackCosts: true,
38
+ slowCallMs: 5000
71
39
  }
72
40
  };
73
41
 
74
42
  /**
75
- * Check if SDK is properly configured and should be active
43
+ * Load configuration from environment variables.
44
+ * Called lazily on first use (e.g., from initialize() or isEnabled()).
45
+ * Safe to call multiple times — only reads env vars once.
46
+ */
47
+ export function loadConfig({ force = false } = {}) {
48
+ if (configLoaded && !force) return;
49
+ configLoaded = true;
50
+
51
+ config.apiKey = process.env.SENTIENGUARD_APM_KEY || '';
52
+ config.service = process.env.SENTIENGUARD_SERVICE || '';
53
+ config.environment = process.env.SENTIENGUARD_ENV || 'production';
54
+ config.endpoint = process.env.SENTIENGUARD_ENDPOINT || 'https://sentienguard-dev.the-algo.com/api/v1/apm/ingest';
55
+ config.flushInterval = parseInt(process.env.SENTIENGUARD_FLUSH_INTERVAL, 10) || 10;
56
+ config.maxRoutes = parseInt(process.env.SENTIENGUARD_MAX_ROUTES, 10) || 100;
57
+ config.maxPayloadSize = parseInt(process.env.SENTIENGUARD_MAX_PAYLOAD_SIZE, 10) || 1024 * 1024;
58
+ config.enabled = process.env.SENTIENGUARD_ENABLED !== 'false';
59
+ config.debug = process.env.SENTIENGUARD_DEBUG === 'true';
60
+
61
+ config.mongodb.enabled = process.env.SENTIENGUARD_MONGODB_ENABLED !== 'false';
62
+ config.mongodb.slowQueryMs = parseInt(process.env.SENTIENGUARD_MONGODB_SLOW_QUERY_MS, 10) || 100;
63
+ config.mongodb.poolStatsInterval = parseInt(process.env.SENTIENGUARD_MONGODB_POOL_INTERVAL, 10) || 10000;
64
+
65
+ config.circuitBreaker.enabled = process.env.SENTIENGUARD_CIRCUIT_BREAKER_ENABLED === 'true';
66
+ config.circuitBreaker.timeout = parseInt(process.env.SENTIENGUARD_CIRCUIT_TIMEOUT_MS, 10) || 3000;
67
+ config.circuitBreaker.errorThresholdPercentage = parseInt(process.env.SENTIENGUARD_CIRCUIT_ERROR_THRESHOLD, 10) || 50;
68
+ config.circuitBreaker.resetTimeout = parseInt(process.env.SENTIENGUARD_CIRCUIT_RESET_TIMEOUT, 10) || 30000;
69
+ config.circuitBreaker.volumeThreshold = parseInt(process.env.SENTIENGUARD_CIRCUIT_VOLUME_THRESHOLD, 10) || 5;
70
+
71
+ config.openai.enabled = process.env.SENTIENGUARD_OPENAI_ENABLED !== 'false';
72
+ config.openai.trackTokens = process.env.SENTIENGUARD_OPENAI_TRACK_TOKENS !== 'false';
73
+ config.openai.trackCosts = process.env.SENTIENGUARD_OPENAI_TRACK_COSTS !== 'false';
74
+ config.openai.slowCallMs = parseInt(process.env.SENTIENGUARD_OPENAI_SLOW_CALL_MS, 10) || 5000;
75
+ }
76
+
77
+ /**
78
+ * Check if SDK is properly configured and should be active.
79
+ * Triggers lazy config load if not yet loaded.
76
80
  */
77
81
  export function isEnabled() {
78
- // SDK disables itself silently if no API key or service name
82
+ loadConfig();
79
83
  return config.enabled && !!config.apiKey && !!config.service;
80
84
  }
81
85
 
82
86
  /**
83
- * Get validated configuration
87
+ * Get validated configuration.
88
+ * Triggers lazy config load if not yet loaded.
84
89
  */
85
90
  export function getConfig() {
91
+ loadConfig();
86
92
  return { ...config };
87
93
  }
88
94
 
@@ -1,236 +1,231 @@
1
- /**
2
- * Dependency Tracking
3
- * Automatically times outgoing HTTP calls (fetch, axios, node http/https).
4
- *
5
- * For each dependency:
6
- * - name (e.g., "OpenAI API", "api.example.com")
7
- * - type (http, db, cache)
8
- * - response time
9
- * - error flag
10
- */
11
-
12
- import http from 'http';
13
- import https from 'https';
14
- import { getAggregator } from './aggregator.js';
15
- import { debug, getConfig } from './config.js';
16
-
17
- let isInstrumented = false;
18
- let originalHttpRequest = null;
19
- let originalHttpsRequest = null;
20
-
21
- // Known service patterns for better naming
22
- const KNOWN_SERVICES = [
23
- { pattern: /openai\.com/i, name: 'OpenAI API' },
24
- { pattern: /anthropic\.com/i, name: 'Anthropic API' },
25
- { pattern: /api\.stripe\.com/i, name: 'Stripe API' },
26
- { pattern: /api\.sendgrid\.com/i, name: 'SendGrid' },
27
- { pattern: /api\.twilio\.com/i, name: 'Twilio API' },
28
- { pattern: /s3\.amazonaws\.com/i, name: 'AWS S3' },
29
- { pattern: /dynamodb\..+\.amazonaws\.com/i, name: 'DynamoDB' },
30
- { pattern: /sqs\..+\.amazonaws\.com/i, name: 'AWS SQS' },
31
- { pattern: /sns\..+\.amazonaws\.com/i, name: 'AWS SNS' },
32
- { pattern: /mongodb\.net/i, name: 'MongoDB Atlas' },
33
- { pattern: /redis/i, name: 'Redis' },
34
- { pattern: /postgresql|postgres/i, name: 'PostgreSQL' },
35
- { pattern: /mysql/i, name: 'MySQL' }
36
- ];
37
-
38
- /**
39
- * Extract a friendly name from hostname
40
- */
41
- function getServiceName(hostname) {
42
- if (!hostname) return 'unknown';
43
-
44
- // Check known services
45
- for (const service of KNOWN_SERVICES) {
46
- if (service.pattern.test(hostname)) {
47
- return service.name;
48
- }
49
- }
50
-
51
- // Default to hostname
52
- return hostname;
53
- }
54
-
55
- /**
56
- * Determine dependency type from hostname/path
57
- */
58
- function getDependencyType(hostname, path) {
59
- const lowerHost = (hostname || '').toLowerCase();
60
- const lowerPath = (path || '').toLowerCase();
61
-
62
- // Database indicators
63
- if (/mongodb|postgres|mysql|dynamodb|redis|memcache/i.test(lowerHost)) {
64
- return 'db';
65
- }
66
-
67
- // Cache indicators
68
- if (/redis|memcache|elasticache/i.test(lowerHost)) {
69
- return 'cache';
70
- }
71
-
72
- // Storage indicators
73
- if (/s3\.amazonaws|storage\.googleapis|blob\.core\.windows/i.test(lowerHost)) {
74
- return 'storage';
75
- }
76
-
77
- // Default to HTTP
78
- return 'http';
79
- }
80
-
81
- /**
82
- * Check if this request should be excluded from tracking
83
- */
84
- function shouldExclude(hostname) {
85
- const config = getConfig();
86
-
87
- // Don't track our own APM endpoint
88
- if (config.endpoint) {
89
- try {
90
- const endpointUrl = new URL(config.endpoint);
91
- if (hostname === endpointUrl.hostname) {
92
- return true;
93
- }
94
- } catch {
95
- // Invalid endpoint URL, continue
96
- }
97
- }
98
-
99
- // Exclude localhost by default (internal services)
100
- if (hostname === 'localhost' || hostname === '127.0.0.1') {
101
- return true;
102
- }
103
-
104
- return false;
105
- }
106
-
107
- /**
108
- * Wrap http/https request to track dependencies
109
- */
110
- function wrapRequest(original, protocol) {
111
- return function instrumentedRequest(options, callback) {
112
- // Parse options to get hostname
113
- let hostname = '';
114
- let path = '/';
115
-
116
- if (typeof options === 'string') {
117
- try {
118
- const url = new URL(options);
119
- hostname = url.hostname;
120
- path = url.pathname;
121
- } catch {
122
- // Invalid URL
123
- }
124
- } else if (options) {
125
- hostname = options.hostname || options.host || '';
126
- path = options.path || '/';
127
- // Remove port from host if present
128
- hostname = hostname.split(':')[0];
129
- }
130
-
131
- // Check exclusions
132
- if (shouldExclude(hostname)) {
133
- return original.apply(this, arguments);
134
- }
135
-
136
- const startTime = process.hrtime.bigint();
137
- const serviceName = getServiceName(hostname);
138
- const depType = getDependencyType(hostname, path);
139
-
140
- // Call original
141
- const req = original.apply(this, arguments);
142
-
143
- // Track response
144
- req.on('response', (res) => {
145
- const endTime = process.hrtime.bigint();
146
- const latencyMs = Number(endTime - startTime) / 1e6;
147
- const isError = res.statusCode >= 400;
148
-
149
- const aggregator = getAggregator();
150
- aggregator.recordDependency(serviceName, depType, latencyMs, isError);
151
-
152
- debug(`Dependency: ${serviceName} (${depType}) ${res.statusCode} ${latencyMs.toFixed(2)}ms`);
153
- });
154
-
155
- // Track errors
156
- req.on('error', () => {
157
- const endTime = process.hrtime.bigint();
158
- const latencyMs = Number(endTime - startTime) / 1e6;
159
-
160
- const aggregator = getAggregator();
161
- aggregator.recordDependency(serviceName, depType, latencyMs, true);
162
-
163
- debug(`Dependency error: ${serviceName} (${depType}) ${latencyMs.toFixed(2)}ms`);
164
- });
165
-
166
- return req;
167
- };
168
- }
169
-
170
- /**
171
- * Instrument outgoing HTTP requests
172
- */
173
- export function instrumentDependencies() {
174
- if (isInstrumented) {
175
- debug('Dependencies already instrumented, skipping');
176
- return;
177
- }
178
-
179
- // Store originals
180
- originalHttpRequest = http.request;
181
- originalHttpsRequest = https.request;
182
-
183
- // Patch http.request
184
- http.request = wrapRequest(originalHttpRequest, 'http');
185
- http.get = function (options, callback) {
186
- const req = http.request(options, callback);
187
- req.end();
188
- return req;
189
- };
190
-
191
- // Patch https.request
192
- https.request = wrapRequest(originalHttpsRequest, 'https');
193
- https.get = function (options, callback) {
194
- const req = https.request(options, callback);
195
- req.end();
196
- return req;
197
- };
198
-
199
- isInstrumented = true;
200
- debug('Dependency instrumentation enabled');
201
- }
202
-
203
- /**
204
- * Remove instrumentation (for testing/cleanup)
205
- */
206
- export function uninstrumentDependencies() {
207
- if (!isInstrumented) return;
208
-
209
- if (originalHttpRequest) {
210
- http.request = originalHttpRequest;
211
- http.get = function (options, callback) {
212
- const req = http.request(options, callback);
213
- req.end();
214
- return req;
215
- };
216
- }
217
-
218
- if (originalHttpsRequest) {
219
- https.request = originalHttpsRequest;
220
- https.get = function (options, callback) {
221
- const req = https.request(options, callback);
222
- req.end();
223
- return req;
224
- };
225
- }
226
-
227
- isInstrumented = false;
228
- debug('Dependency instrumentation disabled');
229
- }
230
-
231
- export default {
232
- instrumentDependencies,
233
- uninstrumentDependencies,
234
- getServiceName,
235
- getDependencyType
236
- };
1
+ /**
2
+ * Dependency Tracking
3
+ * Automatically times outgoing HTTP calls (fetch, axios, node http/https).
4
+ *
5
+ * For each dependency:
6
+ * - name (e.g., "OpenAI API", "api.example.com")
7
+ * - type (http, db, cache)
8
+ * - response time
9
+ * - error flag
10
+ */
11
+
12
+ import http from 'http';
13
+ import https from 'https';
14
+ import { getAggregator } from './aggregator.js';
15
+ import { debug, getConfig } from './config.js';
16
+
17
+ let isInstrumented = false;
18
+ let originalHttpRequest = null;
19
+ let originalHttpsRequest = null;
20
+
21
+ // Known service patterns for better naming
22
+ const KNOWN_SERVICES = [
23
+ { pattern: /openai\.com/i, name: 'OpenAI API' },
24
+ { pattern: /anthropic\.com/i, name: 'Anthropic API' },
25
+ { pattern: /api\.stripe\.com/i, name: 'Stripe API' },
26
+ { pattern: /api\.sendgrid\.com/i, name: 'SendGrid' },
27
+ { pattern: /api\.twilio\.com/i, name: 'Twilio API' },
28
+ { pattern: /s3\.amazonaws\.com/i, name: 'AWS S3' },
29
+ { pattern: /dynamodb\..+\.amazonaws\.com/i, name: 'DynamoDB' },
30
+ { pattern: /sqs\..+\.amazonaws\.com/i, name: 'AWS SQS' },
31
+ { pattern: /sns\..+\.amazonaws\.com/i, name: 'AWS SNS' },
32
+ { pattern: /mongodb\.net/i, name: 'MongoDB Atlas' },
33
+ { pattern: /redis/i, name: 'Redis' },
34
+ { pattern: /postgresql|postgres/i, name: 'PostgreSQL' },
35
+ { pattern: /mysql/i, name: 'MySQL' }
36
+ ];
37
+
38
+ /**
39
+ * Extract a friendly name from hostname
40
+ */
41
+ function getServiceName(hostname) {
42
+ if (!hostname) return 'unknown';
43
+
44
+ // Check known services
45
+ for (const service of KNOWN_SERVICES) {
46
+ if (service.pattern.test(hostname)) {
47
+ return service.name;
48
+ }
49
+ }
50
+
51
+ // Default to hostname
52
+ return hostname;
53
+ }
54
+
55
+ /**
56
+ * Determine dependency type from hostname/path
57
+ */
58
+ function getDependencyType(hostname, path) {
59
+ const lowerHost = (hostname || '').toLowerCase();
60
+
61
+ // Database indicators
62
+ if (/mongodb|postgres|mysql|dynamodb|redis|memcache/i.test(lowerHost)) {
63
+ return 'db';
64
+ }
65
+
66
+ // Cache indicators
67
+ if (/redis|memcache|elasticache/i.test(lowerHost)) {
68
+ return 'cache';
69
+ }
70
+
71
+ // Storage indicators
72
+ if (/s3\.amazonaws|storage\.googleapis|blob\.core\.windows/i.test(lowerHost)) {
73
+ return 'storage';
74
+ }
75
+
76
+ // Default to HTTP
77
+ return 'http';
78
+ }
79
+
80
+ /**
81
+ * Check if this request should be excluded from tracking
82
+ */
83
+ function shouldExclude(hostname) {
84
+ const config = getConfig();
85
+
86
+ // Don't track our own APM endpoint
87
+ if (config.endpoint) {
88
+ try {
89
+ const endpointUrl = new URL(config.endpoint);
90
+ if (hostname === endpointUrl.hostname) {
91
+ return true;
92
+ }
93
+ } catch {
94
+ // Invalid endpoint URL, continue
95
+ }
96
+ }
97
+
98
+ // Exclude localhost by default (internal services)
99
+ return hostname === 'localhost' || hostname === '127.0.0.1';
100
+ }
101
+
102
+ /**
103
+ * Wrap http/https request to track dependencies
104
+ */
105
+ function wrapRequest(original, protocol) {
106
+ return function instrumentedRequest(options, callback) {
107
+ // Parse options to get hostname
108
+ let hostname = '';
109
+ let path = '/';
110
+
111
+ if (typeof options === 'string') {
112
+ try {
113
+ const url = new URL(options);
114
+ hostname = url.hostname;
115
+ path = url.pathname;
116
+ } catch {
117
+ // Invalid URL
118
+ }
119
+ } else if (options) {
120
+ hostname = options.hostname || options.host || '';
121
+ path = options.path || '/';
122
+ // Remove port from host if present
123
+ hostname = hostname.split(':')[0];
124
+ }
125
+
126
+ // Check exclusions
127
+ if (shouldExclude(hostname)) {
128
+ return original.apply(this, arguments);
129
+ }
130
+
131
+ const startTime = process.hrtime.bigint();
132
+ const serviceName = getServiceName(hostname);
133
+ const depType = getDependencyType(hostname, path);
134
+
135
+ // Call original
136
+ const req = original.apply(this, arguments);
137
+
138
+ // Track response
139
+ req.on('response', (res) => {
140
+ const endTime = process.hrtime.bigint();
141
+ const latencyMs = Number(endTime - startTime) / 1e6;
142
+ const isError = res.statusCode >= 400;
143
+
144
+ const aggregator = getAggregator();
145
+ aggregator.recordDependency(serviceName, depType, latencyMs, isError);
146
+
147
+ debug(`Dependency: ${serviceName} (${depType}) ${res.statusCode} ${latencyMs.toFixed(2)}ms`);
148
+ });
149
+
150
+ // Track errors
151
+ req.on('error', () => {
152
+ const endTime = process.hrtime.bigint();
153
+ const latencyMs = Number(endTime - startTime) / 1e6;
154
+
155
+ const aggregator = getAggregator();
156
+ aggregator.recordDependency(serviceName, depType, latencyMs, true);
157
+
158
+ debug(`Dependency error: ${serviceName} (${depType}) ${latencyMs.toFixed(2)}ms`);
159
+ });
160
+
161
+ return req;
162
+ };
163
+ }
164
+
165
+ /**
166
+ * Instrument outgoing HTTP requests
167
+ */
168
+ export function instrumentDependencies() {
169
+ if (isInstrumented) {
170
+ debug('Dependencies already instrumented, skipping');
171
+ return;
172
+ }
173
+
174
+ // Store originals
175
+ originalHttpRequest = http.request;
176
+ originalHttpsRequest = https.request;
177
+
178
+ // Patch http.request
179
+ http.request = wrapRequest(originalHttpRequest, 'http');
180
+ http.get = function (options, callback) {
181
+ const req = http.request(options, callback);
182
+ req.end();
183
+ return req;
184
+ };
185
+
186
+ // Patch https.request
187
+ https.request = wrapRequest(originalHttpsRequest, 'https');
188
+ https.get = function (options, callback) {
189
+ const req = https.request(options, callback);
190
+ req.end();
191
+ return req;
192
+ };
193
+
194
+ isInstrumented = true;
195
+ debug('Dependency instrumentation enabled');
196
+ }
197
+
198
+ /**
199
+ * Remove instrumentation (for testing/cleanup)
200
+ */
201
+ export function uninstrumentDependencies() {
202
+ if (!isInstrumented) return;
203
+
204
+ if (originalHttpRequest) {
205
+ http.request = originalHttpRequest;
206
+ http.get = function (options, callback) {
207
+ const req = http.request(options, callback);
208
+ req.end();
209
+ return req;
210
+ };
211
+ }
212
+
213
+ if (originalHttpsRequest) {
214
+ https.request = originalHttpsRequest;
215
+ https.get = function (options, callback) {
216
+ const req = https.request(options, callback);
217
+ req.end();
218
+ return req;
219
+ };
220
+ }
221
+
222
+ isInstrumented = false;
223
+ debug('Dependency instrumentation disabled');
224
+ }
225
+
226
+ export default {
227
+ instrumentDependencies,
228
+ uninstrumentDependencies,
229
+ getServiceName,
230
+ getDependencyType
231
+ };