@oas-tools/oas-telemetry 0.6.2 → 0.7.0-alpha.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.
Files changed (131) hide show
  1. package/README.md +442 -442
  2. package/dist/{config.cjs → cjs/config.cjs} +6 -7
  3. package/dist/{exporters → cjs/exporters}/InMemoryDBMetricsExporter.cjs +5 -40
  4. package/dist/cjs/exporters/InMemoryDbExporter.cjs +87 -0
  5. package/dist/cjs/exporters/InMemoryLogRecordExporter.cjs +110 -0
  6. package/dist/{exporters → cjs/exporters}/consoleExporter.cjs +2 -7
  7. package/dist/{exporters → cjs/exporters}/dynamicExporter.cjs +12 -19
  8. package/dist/cjs/index.cjs +43 -0
  9. package/dist/cjs/instrumentation/index.cjs +28 -0
  10. package/dist/cjs/instrumentation/logs.cjs +46 -0
  11. package/dist/cjs/instrumentation/metrics.cjs +27 -0
  12. package/dist/cjs/instrumentation/traces.cjs +19 -0
  13. package/dist/{openTelemetry.cjs → cjs/openTelemetry.cjs} +6 -8
  14. package/dist/{systemMetrics.cjs → cjs/systemMetrics.cjs} +7 -7
  15. package/dist/cjs/tlm-ai/agent.cjs +79 -0
  16. package/dist/cjs/tlm-ai/aiController.cjs +69 -0
  17. package/dist/cjs/tlm-ai/aiRoutes.cjs +13 -0
  18. package/dist/cjs/tlm-ai/knownMicroservices.cjs +13 -0
  19. package/dist/cjs/tlm-ai/tools.cjs +504 -0
  20. package/dist/{routes/authRoutes.cjs → cjs/tlm-auth/authController.cjs} +21 -28
  21. package/dist/{middleware → cjs/tlm-auth}/authMiddleware.cjs +1 -1
  22. package/dist/cjs/tlm-auth/authRoutes.cjs +14 -0
  23. package/dist/cjs/tlm-log/logController.cjs +55 -0
  24. package/dist/cjs/tlm-log/logRoutes.cjs +13 -0
  25. package/dist/{routes → cjs/tlm-metric}/metricsRoutes.cjs +1 -2
  26. package/dist/{controllers → cjs/tlm-plugin}/pluginController.cjs +31 -41
  27. package/dist/cjs/tlm-plugin/pluginRoutes.cjs +13 -0
  28. package/dist/{controllers/telemetryController.cjs → cjs/tlm-trace/traceController.cjs} +8 -19
  29. package/dist/cjs/tlm-trace/traceRoutes.cjs +17 -0
  30. package/dist/cjs/tlm-ui/uiController.cjs +27 -0
  31. package/dist/cjs/tlm-ui/uiRoutes.cjs +31 -0
  32. package/dist/cjs/tlm-util/utilController.cjs +63 -0
  33. package/dist/cjs/tlm-util/utilRoutes.cjs +12 -0
  34. package/dist/cjs/tlmRoutes.cjs +79 -0
  35. package/dist/cjs/types/index.cjs +8 -0
  36. package/dist/cjs/utils/circular.cjs +90 -0
  37. package/dist/cjs/utils/logger.cjs +28 -0
  38. package/{src → dist/esm}/config.js +20 -23
  39. package/{src → dist/esm}/exporters/InMemoryDBMetricsExporter.js +57 -111
  40. package/dist/esm/exporters/InMemoryDbExporter.js +87 -0
  41. package/dist/esm/exporters/InMemoryLogRecordExporter.js +95 -0
  42. package/{src → dist/esm}/exporters/consoleExporter.js +38 -47
  43. package/{src → dist/esm}/exporters/dynamicExporter.js +50 -62
  44. package/dist/esm/index.js +39 -0
  45. package/dist/esm/instrumentation/index.js +26 -0
  46. package/dist/esm/instrumentation/logs.js +34 -0
  47. package/dist/esm/instrumentation/metrics.js +18 -0
  48. package/dist/esm/instrumentation/traces.js +12 -0
  49. package/{src → dist/esm}/openTelemetry.js +50 -58
  50. package/dist/esm/systemMetrics.js +82 -0
  51. package/dist/esm/tlm-ai/agent.js +68 -0
  52. package/dist/esm/tlm-ai/aiController.js +45 -0
  53. package/dist/esm/tlm-ai/aiRoutes.js +7 -0
  54. package/dist/esm/tlm-ai/knownMicroservices.js +5 -0
  55. package/dist/esm/tlm-ai/tools.js +490 -0
  56. package/dist/esm/tlm-auth/authController.js +41 -0
  57. package/{src/middleware → dist/esm/tlm-auth}/authMiddleware.js +12 -14
  58. package/dist/esm/tlm-auth/authRoutes.js +7 -0
  59. package/dist/esm/tlm-log/logController.js +36 -0
  60. package/dist/esm/tlm-log/logRoutes.js +7 -0
  61. package/{src/controllers → dist/esm/tlm-metric}/metricsController.js +28 -30
  62. package/{src/routes → dist/esm/tlm-metric}/metricsRoutes.js +8 -15
  63. package/{src/controllers → dist/esm/tlm-plugin}/pluginController.js +103 -115
  64. package/dist/esm/tlm-plugin/pluginRoutes.js +7 -0
  65. package/dist/esm/tlm-trace/traceController.js +54 -0
  66. package/dist/esm/tlm-trace/traceRoutes.js +11 -0
  67. package/dist/esm/tlm-ui/uiController.js +20 -0
  68. package/dist/esm/tlm-ui/uiRoutes.js +23 -0
  69. package/dist/esm/tlm-util/utilController.js +57 -0
  70. package/dist/esm/tlm-util/utilRoutes.js +6 -0
  71. package/dist/esm/tlmRoutes.js +72 -0
  72. package/dist/esm/types/index.js +4 -0
  73. package/dist/esm/utils/circular.js +84 -0
  74. package/dist/esm/utils/logger.js +19 -0
  75. package/dist/types/config.d.ts +6 -0
  76. package/dist/types/exporters/InMemoryDBMetricsExporter.d.ts +15 -0
  77. package/dist/types/exporters/InMemoryDbExporter.d.ts +24 -0
  78. package/dist/types/exporters/InMemoryLogRecordExporter.d.ts +27 -0
  79. package/dist/types/exporters/consoleExporter.d.ts +13 -0
  80. package/dist/types/exporters/dynamicExporter.d.ts +25 -0
  81. package/dist/types/index.d.ts +8 -0
  82. package/dist/types/instrumentation/index.d.ts +1 -0
  83. package/dist/types/instrumentation/logs.d.ts +1 -0
  84. package/dist/types/instrumentation/metrics.d.ts +1 -0
  85. package/dist/types/instrumentation/traces.d.ts +1 -0
  86. package/dist/types/openTelemetry.d.ts +1 -0
  87. package/dist/types/systemMetrics.d.ts +26 -0
  88. package/dist/types/tlm-ai/agent.d.ts +1 -0
  89. package/dist/types/tlm-ai/aiController.d.ts +4 -0
  90. package/dist/types/tlm-ai/aiRoutes.d.ts +2 -0
  91. package/dist/types/tlm-ai/knownMicroservices.d.ts +6 -0
  92. package/dist/types/tlm-ai/tools.d.ts +45 -0
  93. package/dist/types/tlm-auth/authController.d.ts +4 -0
  94. package/dist/types/tlm-auth/authMiddleware.d.ts +2 -0
  95. package/dist/types/tlm-auth/authRoutes.d.ts +2 -0
  96. package/dist/types/tlm-log/logController.d.ts +4 -0
  97. package/dist/types/tlm-log/logRoutes.d.ts +2 -0
  98. package/dist/types/tlm-metric/metricsController.d.ts +4 -0
  99. package/dist/types/tlm-metric/metricsRoutes.d.ts +2 -0
  100. package/dist/types/tlm-plugin/pluginController.d.ts +3 -0
  101. package/dist/types/tlm-plugin/pluginRoutes.d.ts +2 -0
  102. package/dist/types/tlm-trace/traceController.d.ts +7 -0
  103. package/dist/types/tlm-trace/traceRoutes.d.ts +2 -0
  104. package/dist/types/tlm-ui/uiController.d.ts +8 -0
  105. package/dist/types/tlm-ui/uiRoutes.d.ts +2 -0
  106. package/dist/types/tlm-util/utilController.d.ts +3 -0
  107. package/dist/types/tlm-util/utilRoutes.d.ts +2 -0
  108. package/dist/types/tlmRoutes.d.ts +2 -0
  109. package/dist/types/types/index.d.ts +56 -0
  110. package/dist/types/utils/circular.d.ts +31 -0
  111. package/dist/types/utils/logger.d.ts +9 -0
  112. package/dist/ui/assets/index-BNhZBPi2.css +1 -0
  113. package/dist/ui/assets/index-DxGAMrAl.js +401 -0
  114. package/dist/ui/index.html +14 -0
  115. package/dist/ui/vite.svg +1 -0
  116. package/package.json +80 -77
  117. package/dist/controllers/uiController.cjs +0 -78
  118. package/dist/exporters/InMemoryDbExporter.cjs +0 -178
  119. package/dist/index.cjs +0 -110
  120. package/dist/routes/telemetryRoutes.cjs +0 -31
  121. package/dist/services/uiService.cjs +0 -1520
  122. package/src/controllers/telemetryController.js +0 -69
  123. package/src/controllers/uiController.js +0 -69
  124. package/src/dev/ui/login.html +0 -32
  125. package/src/exporters/InMemoryDbExporter.js +0 -181
  126. package/src/index.js +0 -121
  127. package/src/routes/authRoutes.js +0 -53
  128. package/src/routes/telemetryRoutes.js +0 -38
  129. package/src/services/uiService.js +0 -1520
  130. package/src/systemMetrics.js +0 -102
  131. /package/dist/{controllers → cjs/tlm-metric}/metricsController.cjs +0 -0
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getAgentResponse = getAgentResponse;
7
+ var _openai = _interopRequireDefault(require("openai"));
8
+ var _dotenv = _interopRequireDefault(require("dotenv"));
9
+ var _tools = require("./tools.cjs");
10
+ var _logger = _interopRequireDefault(require("../utils/logger.cjs"));
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ _dotenv.default.config();
13
+ let openai;
14
+ try {
15
+ openai = new _openai.default({
16
+ apiKey: process.env.OASTLM_AI_OPENAI_API_KEY,
17
+ dangerouslyAllowBrowser: true
18
+ });
19
+ } catch {
20
+ openai = null;
21
+ }
22
+ const messages = [{
23
+ role: "assistant",
24
+ content: "You are a helpful telemetry assistant. Only use the functions you have been provided with. If the question is not related to the functions, respond with 'I cannot help with that.'. If you need to call to other agents, do so using the tools provided."
25
+ }];
26
+ async function agent(userInput) {
27
+ messages.push({
28
+ role: "user",
29
+ content: userInput
30
+ });
31
+ for (let i = 0; i < 5; i++) {
32
+ const response = await openai?.chat?.completions?.create?.({
33
+ model: process.env.OASTLM_AI_OPENAI_MODEL_NAME || "gpt-4o-mini",
34
+ messages: messages,
35
+ tools: _tools.tools
36
+ });
37
+ const {
38
+ finish_reason,
39
+ message
40
+ } = response.choices[0];
41
+ if (finish_reason === "tool_calls" && message.tool_calls) {
42
+ _logger.default.debug("Tool calls detected:", message.tool_calls);
43
+ const results = [];
44
+ for (const toolCall of message.tool_calls) {
45
+ const functionName = toolCall.function.name;
46
+ const functionToCall = _tools.availableTools[functionName];
47
+ const functionArgs = JSON.parse(toolCall.function.arguments);
48
+ const functionArgsArr = Object.values(functionArgs);
49
+ // @ts-expect-error yes
50
+ // eslint-disable-next-line prefer-spread
51
+ const functionResponse = await functionToCall.apply(null, functionArgsArr);
52
+ results.push({
53
+ name: functionName,
54
+ response: functionResponse
55
+ });
56
+ }
57
+ const resultMessage = results.map(({
58
+ name,
59
+ response
60
+ }) => `Result from "${name}":\n${JSON.stringify(response, null, 2)}`).join("\n\n");
61
+ messages.push({
62
+ role: "function",
63
+ name: "multiple_tool_calls",
64
+ content: resultMessage
65
+ });
66
+ } else if (finish_reason === "stop") {
67
+ messages.push(message);
68
+ return message;
69
+ }
70
+ }
71
+ return {
72
+ content: "Se alcanzó el número máximo de iteraciones sin una respuesta adecuada. Intenta con una consulta más específica."
73
+ };
74
+ }
75
+ async function getAgentResponse(question) {
76
+ const response = await agent(question);
77
+ _logger.default.debug("Response from agent:", response);
78
+ return response.content;
79
+ }
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.setKnownMicroservicesHandler = exports.getKnownMicroservicesHandler = exports.answerQuestion = void 0;
7
+ var _agent = require("./agent.cjs");
8
+ var _knownMicroservices = require("./knownMicroservices.cjs");
9
+ var _logger = _interopRequireDefault(require("../utils/logger.cjs"));
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ const answerQuestion = async (req, res) => {
12
+ try {
13
+ const {
14
+ question
15
+ } = req.body;
16
+ if (!question) res.status(400).json({
17
+ error: 'Missing question'
18
+ });
19
+ const answer = await (0, _agent.getAgentResponse)(question);
20
+ res.json({
21
+ answer
22
+ });
23
+ } catch (error) {
24
+ _logger.default.error(error);
25
+ res.status(500).json({
26
+ error: 'Internal error'
27
+ });
28
+ }
29
+ };
30
+ exports.answerQuestion = answerQuestion;
31
+ const setKnownMicroservicesHandler = (req, res) => {
32
+ try {
33
+ const {
34
+ microservices
35
+ } = req.body;
36
+ if (!Array.isArray(microservices)) {
37
+ res.status(400).json({
38
+ error: 'Invalid microservices format. Expected an array.'
39
+ });
40
+ return;
41
+ }
42
+ (0, _knownMicroservices.setKnownMicroservices)(microservices);
43
+ res.json({
44
+ message: "Microservices configuration updated successfully.",
45
+ knownMicroservices: (0, _knownMicroservices.getKnownMicroservices)(),
46
+ note: "In the future, OAS-Telemetry will support autodiscovery, making this configuration unnecessary."
47
+ });
48
+ } catch (error) {
49
+ _logger.default.error(error);
50
+ res.status(500).json({
51
+ error: 'Internal error'
52
+ });
53
+ }
54
+ };
55
+ exports.setKnownMicroservicesHandler = setKnownMicroservicesHandler;
56
+ const getKnownMicroservicesHandler = (req, res) => {
57
+ try {
58
+ const microservices = (0, _knownMicroservices.getKnownMicroservices)();
59
+ res.json({
60
+ knownMicroservices: microservices
61
+ });
62
+ } catch (error) {
63
+ _logger.default.error(error);
64
+ res.status(500).json({
65
+ error: 'Internal error'
66
+ });
67
+ }
68
+ };
69
+ exports.getKnownMicroservicesHandler = getKnownMicroservicesHandler;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.aiRoutes = void 0;
7
+ var _express = require("express");
8
+ var _aiController = require("./aiController.cjs");
9
+ const aiRoutes = exports.aiRoutes = (0, _express.Router)();
10
+ aiRoutes.post('/chat', _aiController.answerQuestion);
11
+ aiRoutes.post('/microservices', _aiController.setKnownMicroservicesHandler); // New route for configuring microservices
12
+ aiRoutes.get('/microservices', _aiController.getKnownMicroservicesHandler); // Route to retrieve the list of known microservices
13
+ var _default = exports.default = aiRoutes;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.setKnownMicroservices = exports.getKnownMicroservices = void 0;
7
+ let knownMicroservices = null;
8
+ const getKnownMicroservices = () => knownMicroservices || [];
9
+ exports.getKnownMicroservices = getKnownMicroservices;
10
+ const setKnownMicroservices = microservices => {
11
+ knownMicroservices = microservices;
12
+ };
13
+ exports.setKnownMicroservices = setKnownMicroservices;
@@ -0,0 +1,504 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.tools = exports.availableTools = void 0;
7
+ var _axios = _interopRequireDefault(require("axios"));
8
+ var _config = require("../config.cjs");
9
+ var _logger = _interopRequireDefault(require("../utils/logger.cjs"));
10
+ var _knownMicroservices = require("./knownMicroservices.cjs");
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ const getTraces = async searchInput => {
13
+ _logger.default.debug("getTraces called with searchInput:", searchInput);
14
+ try {
15
+ const search = searchInput || {};
16
+ const traces = await new Promise((resolve, reject) => {
17
+ _config.globalOasTlmConfig.dynamicSpanExporter.exporter.find(search, (err, docs) => {
18
+ if (err) reject(err);else resolve(docs);
19
+ });
20
+ });
21
+ const simplifiedTraces = getSimplifiedTraces(traces);
22
+ _logger.default.debug(`Searching for traces with searchInput: ${JSON.stringify(search)}`);
23
+ _logger.default.debug(`Traces found: ${JSON.stringify(simplifiedTraces.length)}`);
24
+ return {
25
+ traces: simplifiedTraces
26
+ };
27
+ } catch (error) {
28
+ _logger.default.error('Error fetching traces:', error);
29
+ throw error;
30
+ }
31
+ };
32
+ const getLogs = async (startDate, endDate) => {
33
+ _logger.default.debug("getLogs called with startDate:", startDate, "endDate:", endDate);
34
+ try {
35
+ let nedbQuery = {};
36
+ if (!startDate && !endDate) {
37
+ _logger.default.debug("No date range provided, fetching all logs.");
38
+ } else {
39
+ _logger.default.debug(`Fetching logs from ${startDate} to ${endDate}`);
40
+ nedbQuery = {
41
+ timestamp: {
42
+ $gte: startDate ? new Date(startDate).getTime() : 0,
43
+ // Epoch ms
44
+ $lte: endDate ? new Date(endDate).getTime() : Date.now() // Epoch ms
45
+ }
46
+ };
47
+ }
48
+ const logs = [];
49
+ await new Promise((resolve, reject) => {
50
+ _config.globalOasTlmConfig.debugExporter.find(nedbQuery, null, (err, docs) => {
51
+ if (err) {
52
+ reject(err);
53
+ } else {
54
+ logs.push(...docs);
55
+ _logger.default.debug(`Found ${logs.length} logs in the specified range.`);
56
+ resolve();
57
+ }
58
+ });
59
+ });
60
+ const simplifiedLogs = getSimplifiedLogs(logs);
61
+ return {
62
+ logs: simplifiedLogs
63
+ };
64
+ } catch (error) {
65
+ _logger.default.error('Error fetching logs:', error);
66
+ throw error;
67
+ }
68
+ };
69
+ const getMetrics = async searchInput => {
70
+ _logger.default.debug("getMetrics called with searchInput:", searchInput);
71
+ try {
72
+ const search = searchInput || {};
73
+ const metrics = await new Promise((resolve, reject) => {
74
+ _config.globalOasTlmConfig.metricsExporter.find(search, (err, docs) => {
75
+ if (err) reject(err);else resolve(docs || []);
76
+ });
77
+ });
78
+ const simplifiedMetrics = getSimplifiedMetrics(metrics);
79
+ _logger.default.debug(`Searching for metrics with searchInput: ${JSON.stringify(search)}`);
80
+ _logger.default.debug(`Metrics found: ${JSON.stringify(simplifiedMetrics.length)}`);
81
+ return {
82
+ metrics: simplifiedMetrics
83
+ };
84
+ } catch (error) {
85
+ _logger.default.error('Error fetching metrics:', error);
86
+ throw error;
87
+ }
88
+ };
89
+ const getCurrentTimestampInEpoch = () => {
90
+ _logger.default.debug("Getting the current timestamp in epoch format...");
91
+ const now = new Date();
92
+ return {
93
+ currentTimestampInEpoch: now.getTime(),
94
+ currentTimestampInEpochSeconds: Math.floor(now.getTime() / 1000)
95
+ };
96
+ };
97
+ const startTelemetry = () => {
98
+ _logger.default.debug("Starting telemetry...");
99
+ _config.globalOasTlmConfig.dynamicSpanExporter.exporter.start();
100
+ };
101
+ const stopTelemetry = () => {
102
+ _logger.default.debug("Stopping telemetry...");
103
+ _config.globalOasTlmConfig.dynamicSpanExporter.exporter.stop();
104
+ };
105
+ const resetTelemetry = () => {
106
+ _logger.default.debug("Resetting telemetry...");
107
+ _config.globalOasTlmConfig.dynamicSpanExporter.exporter.reset();
108
+ };
109
+ const getTelemetryStatus = () => {
110
+ _logger.default.debug("Getting telemetry status...");
111
+ const isRunning = _config.globalOasTlmConfig.dynamicSpanExporter.exporter.isRunning() || false;
112
+ return {
113
+ active: isRunning
114
+ };
115
+ };
116
+ const talkToExternalMicroserviceAgent = async (message, microserviceId) => {
117
+ _logger.default.debug("talkToExternalMicroserviceAgent called with question:", message, "microservice:", microserviceId);
118
+ const knownMicroservices = (0, _knownMicroservices.getKnownMicroservices)();
119
+ const identifiedMicroservice = knownMicroservices.find(m => m.id === microserviceId);
120
+ if (!identifiedMicroservice) {
121
+ _logger.default.error(`Agent tried to call an unknown microservice: ${microserviceId}, available microservices: ${knownMicroservices.map(m => m.id).join(', ')}`);
122
+ return {
123
+ microservice: microserviceId,
124
+ response: `I cannot help with that. The microservice ${microserviceId} is not recognized. Available microservices are: ${knownMicroservices.map(m => m.id).join(', ')}`
125
+ };
126
+ }
127
+ const microserviceResponse = await _axios.default.post(identifiedMicroservice.url, {
128
+ question: message
129
+ });
130
+ return {
131
+ microservice: microserviceId,
132
+ response: microserviceResponse.data
133
+ };
134
+ };
135
+ const getMicroserviceAgents = () => {
136
+ _logger.default.debug("Getting microservice agents...");
137
+ return (0, _knownMicroservices.getKnownMicroservices)();
138
+ };
139
+ const tools = exports.tools = [{
140
+ type: "function",
141
+ function: {
142
+ name: "getTraces",
143
+ description: `Fetches trace data for the microservice.
144
+ Traces provide detailed information about requests and their lifecycle, including HTTP attributes (e.g., URL, method, status code),
145
+ network details (e.g., peer IP, port), and timing information.
146
+ The 'searchInput' parameter is an object used to filter traces based on specific criteria.
147
+ This is a NeDB query using MongoDB-like syntax (neDB). If 'searchInput' is null, all traces will be fetched.
148
+ Providing specific filters improves performance.
149
+
150
+ Available properties for filtering:
151
+ {
152
+ "name": "GET", // Name of the span
153
+ "kind": 1, // 1 for incoming requests, 2 for outgoing requests
154
+ "attributes": {
155
+ "http": {
156
+ "url": "http://localhost:3002/api/v1/greet",
157
+ "host": "localhost:3002",
158
+ "method": "GET",
159
+ "scheme": "http",
160
+ "target": "/api/v1/greet",
161
+ "user_agent": "PostmanRuntime/7.44.0",
162
+ "request_content_length_uncompressed": 39,
163
+ "flavor": "1.1",
164
+ "status_code": 200,
165
+ "status_text": "OK"
166
+ },
167
+ "net": {
168
+ "host": {
169
+ "name": "localhost",
170
+ "ip": "::1",
171
+ "port": 3002
172
+ },
173
+ "transport": "ip_tcp",
174
+ "peer": {
175
+ "ip": "::1",
176
+ "port": 50361
177
+ }
178
+ }
179
+ },
180
+ "traceId": "5f7df252eb00e873bbd6441f86b71dac",
181
+ "spanId": "fbd8ea558dd6ac32",
182
+ "service": "oas-telemetry-service",
183
+ "startTime": { "0": 1747666254, "1": 333000000 },
184
+ "endTime": { "0": 1747666254, "1": 335071700 },
185
+ "_duration": { "0": 0, "1": 2071700 }
186
+ }
187
+
188
+
189
+ you can use $or, or $gte or operators like that if needed never > or similar.
190
+ Take into account that startTime.0 and endTime.0 are in epoch SECONDS format not milliseconds.
191
+ For time search ALWAYS use "endTime.0": { "$gte": number } or similar with other operators and startTime.0.
192
+ Common filters include HTTP attributes (e.g., method, status code, URL), timestamps (e.g., 'endTime.0'), or duration ('_duration').
193
+
194
+ Example 'query':
195
+ {
196
+ "attributes.http.method": "GET",
197
+ "attributes.http.status_code": 200, //when asked for ANY error you can use $gte : 400 operator
198
+ "attributes.http.url": "http://localhost:3002/api/v1/greet",
199
+ "_duration": { "$lte": 5000000 },
200
+ "endTime.0": { "$gte": 1747666254 },
201
+ }
202
+ you must give a {searchInput: query} object to the function
203
+
204
+ `,
205
+ parameters: {
206
+ type: "object",
207
+ properties: {
208
+ searchInput: {
209
+ type: "object",
210
+ description: `Optional search criteria for filtering traces.
211
+ This is a NeDB query using MongoDB-like (neDB) syntax.
212
+ For example, you can filter by HTTP attributes, timestamps, or duration.
213
+ If null, all traces will be returned.`,
214
+ additionalProperties: true
215
+ }
216
+ },
217
+ required: ["searchInput"]
218
+ }
219
+ }
220
+ }, {
221
+ type: "function",
222
+ function: {
223
+ name: "getLogs",
224
+ description: `Fetches log data for the microservice.
225
+ Logs provide information about system events, including timestamps, log levels (e.g., info, error), and messages.
226
+ The 'startDate' and 'endDate' parameters define the time range for fetching logs.
227
+ If don't provide a range, all logs will be fetched. Providing a specific range improves performance.
228
+ Example 'startDate' and 'endDate':
229
+ {
230
+ "startDate": "2023-10-01T00:00:00Z",
231
+ "endDate": "2023-10-02T00:00:00Z"
232
+ }
233
+ Common filters include timestamps or log levels.`,
234
+ parameters: {
235
+ type: "object",
236
+ properties: {
237
+ startDate: {
238
+ type: "string"
239
+ },
240
+ endDate: {
241
+ type: "string"
242
+ }
243
+ }
244
+ }
245
+ }
246
+ }, {
247
+ type: "function",
248
+ function: {
249
+ name: "getMetrics",
250
+ description: `Fetches metrics data for the microservice.
251
+ Metrics provide performance-related data, such as CPU usage, memory usage, and process-specific metrics.
252
+ The 'searchInput' parameter is an object used to filter metrics based on specific criteria.
253
+ This is a NeDB query using MongoDB-like (NeDB) syntax. If 'searchInput' is null, all metrics will be fetched. Providing specific filters improves performance.
254
+
255
+ Example 'searchInput':
256
+ {
257
+ "timestamp": { "$gte": 1747651105757, "$lte": 1747651200935 }
258
+ }
259
+
260
+ Common filters include timestamps.`,
261
+ parameters: {
262
+ type: "object",
263
+ properties: {
264
+ searchInput: {
265
+ type: "object",
266
+ description: `Optional search criteria for filtering metrics.
267
+ This is a NeDB query using MongoDB-like (NeDB) syntax.
268
+ For example, you can filter by timestamps.
269
+ If null, all metrics will be returned.`,
270
+ properties: {
271
+ "timestamp": {
272
+ type: "object",
273
+ properties: {
274
+ "$gte": {
275
+ type: "integer"
276
+ },
277
+ "$lte": {
278
+ type: "integer"
279
+ }
280
+ }
281
+ },
282
+ "cpuUsageData.cpuNumber": {
283
+ type: "string"
284
+ },
285
+ "memoryData.used": {
286
+ type: "integer"
287
+ }
288
+ }
289
+ }
290
+ },
291
+ required: ["searchInput"]
292
+ }
293
+ }
294
+ }, {
295
+ type: "function",
296
+ function: {
297
+ name: "startTelemetry",
298
+ description: `Starts the telemetry data collection process.
299
+ This function initializes the telemetry system and begins capturing trace, log, and metric data.`,
300
+ parameters: {}
301
+ }
302
+ }, {
303
+ type: "function",
304
+ function: {
305
+ name: "stopTelemetry",
306
+ description: `Stops the telemetry data collection process.
307
+ This function halts the telemetry system and stops capturing trace, log, and metric data.`,
308
+ parameters: {}
309
+ }
310
+ }, {
311
+ type: "function",
312
+ function: {
313
+ name: "resetTelemetry",
314
+ description: `Resets the telemetry data collection process.
315
+ This function clears any existing telemetry data and prepares the system for a fresh start.`,
316
+ parameters: {}
317
+ }
318
+ }, {
319
+ type: "function",
320
+ function: {
321
+ name: "getTelemetryStatus",
322
+ description: `Retrieves the current status of the telemetry system.
323
+ This function checks whether the telemetry system is currently active or inactive.`,
324
+ parameters: {}
325
+ }
326
+ }, {
327
+ type: "function",
328
+ function: {
329
+ name: "getCurrentTimestampInEpoch",
330
+ description: `Retrieves the current timestamp in epoch format (miliseconds or seconds).
331
+ This function calculates the timestamp for the current moment in milliseconds since the Unix epoch.in .currentTimestampInEpoch. Also returns the current timestamp in seconds in .currentTimestampInEpochSeconds.`,
332
+ parameters: {}
333
+ }
334
+ }, {
335
+ type: "function",
336
+ function: {
337
+ name: "talkToExternalMicroserviceAgent",
338
+ description: `Use this function to communicate with external microservice agent.
339
+ if you want to talk to a microservice agent, you must provide the message and the microservice you want to talk to.
340
+ When you call this function, it will send the message to the specified microservice and return the response.
341
+
342
+ Example 'message':
343
+ {
344
+ "message": "What is the status of the service?",
345
+ "microservice": "Reporter"
346
+ }
347
+
348
+ Microservices Availables (by ID):
349
+ ${(0, _knownMicroservices.getKnownMicroservices)().map(m => m.id).join(", ")}
350
+ `,
351
+ parameters: {
352
+ type: "object",
353
+ properties: {
354
+ message: {
355
+ type: "string",
356
+ description: `The message to be sent to the external microservice agent.`
357
+ },
358
+ microservice: {
359
+ type: "string"
360
+ }
361
+ },
362
+ required: ["message", "microservice"]
363
+ }
364
+ }
365
+ }, {
366
+ type: "function",
367
+ function: {
368
+ name: "getMicroserviceAgents",
369
+ description: `Retrieves the list of available microservice agents.
370
+ This function provides information about the microservices that can be communicated with.`,
371
+ parameters: {}
372
+ }
373
+ }];
374
+ const availableTools = exports.availableTools = {
375
+ getTraces,
376
+ getLogs,
377
+ getMetrics,
378
+ startTelemetry,
379
+ stopTelemetry,
380
+ resetTelemetry,
381
+ getTelemetryStatus,
382
+ getCurrentTimestampInEpoch,
383
+ talkToExternalMicroserviceAgent,
384
+ getMicroserviceAgents
385
+ };
386
+ function getSimplifiedMetrics(metrics) {
387
+ return metrics.map(resourceMetric => {
388
+ const serviceName = resourceMetric.resource?._memoizedAttributes?.service?.name || 'unknown-service';
389
+ const cpuUtilization = {};
390
+ let cpuCount = 0;
391
+ const memoryUsageMB = {
392
+ used: 0,
393
+ free: 0
394
+ };
395
+ const memoryUtilizationPercent = {
396
+ used: 0,
397
+ free: 0
398
+ };
399
+ const networkIO = {
400
+ transmit: 0,
401
+ receive: 0
402
+ };
403
+ const processCPU = {};
404
+ let processMemoryUsage = 0;
405
+ for (const scopeMetric of resourceMetric.scopeMetrics) {
406
+ for (const metric of scopeMetric.metrics) {
407
+ const name = metric.descriptor.name;
408
+ if (name === 'system.cpu.utilization') {
409
+ const stateSums = {};
410
+ const stateCounts = {};
411
+ for (const dp of metric.dataPoints) {
412
+ const state = dp.attributes?.system?.cpu?.state;
413
+ if (!state) continue;
414
+ // @ts-expect-error index signature
415
+ stateSums[state] = (stateSums[state] || 0) + dp.value;
416
+ // @ts-expect-error index signature
417
+ stateCounts[state] = (stateCounts[state] || 0) + 1;
418
+ }
419
+ for (const state in stateSums) {
420
+ // @ts-expect-error index signature
421
+ cpuUtilization[state] = stateSums[state] / stateCounts[state];
422
+ }
423
+ cpuCount = Math.max(...metric.dataPoints.map(dp => parseInt(dp.attributes?.system?.cpu?.debugical_number || 0, 10))) + 1;
424
+ }
425
+ if (name === 'system.memory.usage') {
426
+ for (const dp of metric.dataPoints) {
427
+ const state = dp.attributes?.system?.memory?.state;
428
+ // @ts-expect-error index signature
429
+ if (state) memoryUsageMB[state] = dp.value;
430
+ }
431
+ }
432
+ if (name === 'system.memory.utilization') {
433
+ for (const dp of metric.dataPoints) {
434
+ const state = dp.attributes?.system?.memory?.state;
435
+ // @ts-expect-error index signature
436
+ if (state) memoryUtilizationPercent[state] = dp.value;
437
+ }
438
+ }
439
+ if (name === 'system.network.io') {
440
+ for (const dp of metric.dataPoints) {
441
+ const direction = dp.attributes?.network?.io?.direction;
442
+ // @ts-expect-error index signature
443
+ if (direction) networkIO[direction] += dp.value;
444
+ }
445
+ }
446
+ if (name === 'process.cpu.time') {
447
+ for (const dp of metric.dataPoints) {
448
+ const state = dp.attributes?.process?.cpu?.state;
449
+ // @ts-expect-error index signature
450
+ if (state) processCPU[state] = dp.value;
451
+ }
452
+ }
453
+ if (name === 'process.memory.usage') {
454
+ processMemoryUsage = metric.dataPoints[0]?.value || 0;
455
+ }
456
+ }
457
+ }
458
+ return {
459
+ service: serviceName,
460
+ cpu: {
461
+ avgUtilization: cpuUtilization,
462
+ cores: cpuCount
463
+ },
464
+ memory: {
465
+ usedGB: (memoryUsageMB.used || 0) / 1024 ** 3,
466
+ freeGB: (memoryUsageMB.free || 0) / 1024 ** 3,
467
+ usedPercent: (memoryUtilizationPercent.used || 0) * 100,
468
+ freePercent: (1 - (memoryUtilizationPercent.used || 0)) * 100
469
+ },
470
+ network: {
471
+ transmittedMB: networkIO.transmit / 1024 ** 2,
472
+ receivedMB: networkIO.receive / 1024 ** 2
473
+ },
474
+ process: {
475
+ cpuTimeSec: processCPU,
476
+ memoryUsageMB: processMemoryUsage / 1024 ** 2
477
+ }
478
+ };
479
+ });
480
+ }
481
+ function getSimplifiedTraces(spans) {
482
+ return spans.map(span => {
483
+ return {
484
+ name: span.name,
485
+ kind: span.kind,
486
+ attributes: span.attributes,
487
+ resource: span.resource,
488
+ _spanContext: span._spanContext,
489
+ startTime: span.startTime,
490
+ endTime: span.endTime,
491
+ _duration: span._duration
492
+ };
493
+ });
494
+ }
495
+ function getSimplifiedLogs(logs) {
496
+ return logs.map(log => ({
497
+ service: log.resource?.attributes?.service?.name || undefined,
498
+ timestamp: log.timestamp,
499
+ message: log.body,
500
+ traceId: log.traceId,
501
+ spanId: log.spanId,
502
+ source: log.attributes?.source?.source || undefined
503
+ }));
504
+ }