@oas-tools/oas-telemetry 0.7.0-alpha.5 → 0.7.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 (106) hide show
  1. package/.env.example +2 -0
  2. package/README.md +35 -17
  3. package/dist/cjs/config/bootConfig.cjs +3 -1
  4. package/dist/cjs/docs/openapi.yaml +1399 -0
  5. package/dist/cjs/routesManager.cjs +1 -1
  6. package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.cjs +43 -13
  7. package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.cjs +10 -2
  8. package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.cjs +21 -16
  9. package/dist/cjs/telemetry/initializeTelemetry.cjs +39 -15
  10. package/dist/cjs/telemetry/telemetryConfigurator.cjs +6 -9
  11. package/dist/cjs/telemetry/telemetryRegistry.cjs +11 -8
  12. package/dist/cjs/tlm-ai/agent.cjs +54 -84
  13. package/dist/cjs/tlm-ai/aiController.cjs +69 -47
  14. package/dist/cjs/tlm-ai/aiRoutes.cjs +10 -3
  15. package/dist/cjs/tlm-ai/aiService.cjs +109 -0
  16. package/dist/cjs/tlm-ai/tools.cjs +30 -268
  17. package/dist/cjs/tlm-auth/authController.cjs +9 -9
  18. package/dist/cjs/tlm-auth/authMiddleware.cjs +1 -1
  19. package/dist/cjs/tlm-log/logController.cjs +30 -36
  20. package/dist/cjs/tlm-log/logRoutes.cjs +3 -2
  21. package/dist/cjs/tlm-metric/metricsController.cjs +15 -8
  22. package/dist/cjs/tlm-metric/metricsRoutes.cjs +2 -1
  23. package/dist/cjs/tlm-plugin/pluginController.cjs +11 -1
  24. package/dist/cjs/tlm-plugin/pluginProcess.cjs +4 -2
  25. package/dist/cjs/tlm-plugin/pluginService.cjs +3 -0
  26. package/dist/cjs/tlm-trace/traceController.cjs +16 -9
  27. package/dist/cjs/tlm-trace/traceRoutes.cjs +2 -1
  28. package/dist/cjs/tlm-util/utilController.cjs +23 -2
  29. package/dist/cjs/tlm-util/utilRoutes.cjs +44 -5
  30. package/dist/cjs/utils/logger.cjs +35 -13
  31. package/dist/esm/config/bootConfig.js +2 -0
  32. package/dist/esm/docs/openapi.yaml +1399 -0
  33. package/dist/esm/routesManager.js +1 -1
  34. package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.js +32 -11
  35. package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.js +10 -2
  36. package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.js +20 -13
  37. package/dist/esm/telemetry/initializeTelemetry.js +22 -14
  38. package/dist/esm/telemetry/telemetryConfigurator.js +7 -10
  39. package/dist/esm/telemetry/telemetryRegistry.js +10 -7
  40. package/dist/esm/tlm-ai/agent.js +37 -78
  41. package/dist/esm/tlm-ai/aiController.js +56 -39
  42. package/dist/esm/tlm-ai/aiRoutes.js +11 -4
  43. package/dist/esm/tlm-ai/aiService.js +94 -0
  44. package/dist/esm/tlm-ai/tools.js +29 -255
  45. package/dist/esm/tlm-auth/authController.js +8 -8
  46. package/dist/esm/tlm-auth/authMiddleware.js +1 -1
  47. package/dist/esm/tlm-log/logController.js +26 -28
  48. package/dist/esm/tlm-log/logRoutes.js +4 -3
  49. package/dist/esm/tlm-metric/metricsController.js +10 -6
  50. package/dist/esm/tlm-metric/metricsRoutes.js +3 -2
  51. package/dist/esm/tlm-plugin/pluginController.js +2 -1
  52. package/dist/esm/tlm-plugin/pluginProcess.js +4 -2
  53. package/dist/esm/tlm-plugin/pluginService.js +4 -0
  54. package/dist/esm/tlm-trace/traceController.js +11 -7
  55. package/dist/esm/tlm-trace/traceRoutes.js +3 -2
  56. package/dist/esm/tlm-util/utilController.js +22 -0
  57. package/dist/esm/tlm-util/utilRoutes.js +40 -5
  58. package/dist/esm/utils/logger.js +35 -12
  59. package/dist/types/config/bootConfig.d.ts +1 -0
  60. package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.d.ts +7 -1
  61. package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.d.ts +1 -0
  62. package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.d.ts +1 -0
  63. package/dist/types/telemetry/telemetryRegistry.d.ts +22 -6
  64. package/dist/types/tlm-ai/agent.d.ts +2 -2
  65. package/dist/types/tlm-ai/aiController.d.ts +5 -4
  66. package/dist/types/tlm-ai/aiRoutes.d.ts +1 -1
  67. package/dist/types/tlm-ai/aiService.d.ts +38 -0
  68. package/dist/types/tlm-ai/tools.d.ts +5 -14
  69. package/dist/types/tlm-log/logController.d.ts +2 -2
  70. package/dist/types/tlm-metric/metricsController.d.ts +2 -1
  71. package/dist/types/tlm-plugin/pluginService.d.ts +2 -0
  72. package/dist/types/tlm-trace/traceController.d.ts +2 -1
  73. package/dist/types/tlm-util/utilController.d.ts +1 -0
  74. package/dist/types/utils/logger.d.ts +5 -5
  75. package/dist/ui/assets/ApiDocsPage-C_VVPPHa.js +16 -0
  76. package/dist/ui/assets/CollapsibleCard-B3KR_8mL.js +1 -0
  77. package/dist/ui/assets/DevToolsPage-OyZcDcmw.js +1 -0
  78. package/dist/ui/assets/LandingPage-CppFBA6K.js +6 -0
  79. package/dist/ui/assets/LogsPage-9Fq8GArS.js +26 -0
  80. package/dist/ui/assets/NotFoundPage-B3quk3P1.js +1 -0
  81. package/dist/ui/assets/PluginCreatePage-X_aCH4t4.js +50 -0
  82. package/dist/ui/assets/PluginPage-DMDSihrZ.js +27 -0
  83. package/dist/ui/assets/alert-jQ9HCPIf.js +1133 -0
  84. package/dist/ui/assets/badge-CNq0-mH5.js +1 -0
  85. package/dist/ui/assets/card-DFAwwhN3.js +1 -0
  86. package/dist/ui/assets/chevron-down-CPsvsmqj.js +6 -0
  87. package/dist/ui/assets/chevron-up-Df9jMo1X.js +6 -0
  88. package/dist/ui/assets/circle-alert-DOPQPvU8.js +6 -0
  89. package/dist/ui/assets/index-BkD6DijD.js +15 -0
  90. package/dist/ui/assets/index-CERGVYZK.js +292 -0
  91. package/dist/ui/assets/index-CSIPf9qw.css +1 -0
  92. package/dist/ui/assets/input-Dzvg_ZEZ.js +1 -0
  93. package/dist/ui/assets/label-DuVnkZ4q.js +1 -0
  94. package/dist/ui/assets/loader-circle-CrvlRy5o.js +6 -0
  95. package/dist/ui/assets/loginPage-qa4V-B70.js +6 -0
  96. package/dist/ui/assets/select-DhS8YUtJ.js +1 -0
  97. package/dist/ui/assets/separator-isK4chBP.js +6 -0
  98. package/dist/ui/assets/severityOptions-O38dSOfk.js +11 -0
  99. package/dist/ui/assets/switch-Z3mImG9n.js +1 -0
  100. package/dist/ui/assets/tabs-_77MUUQe.js +16 -0
  101. package/dist/ui/assets/upload-C1LT4Gkb.js +16 -0
  102. package/dist/ui/assets/utilService-DNyqzwj0.js +1 -0
  103. package/dist/ui/index.html +2 -2
  104. package/package.json +17 -6
  105. package/dist/ui/assets/index-Bgd7fFFH.js +0 -1743
  106. package/dist/ui/assets/index-Cz3N1n1Q.css +0 -1
@@ -3,68 +3,90 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
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 = oasTlmConfig => async (req, res) => {
6
+ exports.createConversation = createConversation;
7
+ exports.deleteConversation = deleteConversation;
8
+ exports.getConversationHistory = getConversationHistory;
9
+ exports.listConversations = listConversations;
10
+ exports.sendMessage = sendMessage;
11
+ var _aiService = require("./aiService.cjs");
12
+ async function createConversation(req, res) {
12
13
  try {
13
- const {
14
- question
15
- } = req.body;
16
- if (!question) res.status(400).json({
17
- error: 'Missing question'
18
- });
19
- const getAgentResponse = (0, _agent.getAgent)(oasTlmConfig);
20
- const answer = await getAgentResponse(question);
21
- res.json({
22
- answer
14
+ const conversation = (0, _aiService.getAiService)().createConversation();
15
+ res.status(201).json(conversation);
16
+ } catch (err) {
17
+ res.status(500).json({
18
+ error: err.message
23
19
  });
24
- } catch (error) {
25
- _logger.default.error(error);
20
+ }
21
+ }
22
+ async function listConversations(req, res) {
23
+ try {
24
+ // Only return id and name for each conversation
25
+ const conversations = (0, _aiService.getAiService)().listConversationsMinimal();
26
+ res.json(conversations);
27
+ } catch (err) {
26
28
  res.status(500).json({
27
- error: 'Internal error'
29
+ error: err.message
28
30
  });
29
31
  }
30
- };
31
- exports.answerQuestion = answerQuestion;
32
- const setKnownMicroservicesHandler = () => (req, res) => {
32
+ }
33
+ async function getConversationHistory(req, res) {
33
34
  try {
34
35
  const {
35
- microservices
36
- } = req.body;
37
- if (!Array.isArray(microservices)) {
38
- res.status(400).json({
39
- error: 'Invalid microservices format. Expected an array.'
36
+ conversationId
37
+ } = req.params;
38
+ const conversation = (0, _aiService.getAiService)().getConversation(conversationId);
39
+ if (!conversation) {
40
+ res.status(404).json({
41
+ error: 'Not found'
40
42
  });
41
43
  return;
42
44
  }
43
- (0, _knownMicroservices.setKnownMicroservices)(microservices);
44
- res.json({
45
- message: "Microservices configuration updated successfully.",
46
- knownMicroservices: (0, _knownMicroservices.getKnownMicroservices)(),
47
- note: "In the future, OAS-Telemetry will support autodiscovery, making this configuration unnecessary."
48
- });
49
- } catch (error) {
50
- _logger.default.error(error);
45
+ res.json(conversation);
46
+ } catch (err) {
51
47
  res.status(500).json({
52
- error: 'Internal error'
48
+ error: err.message
53
49
  });
54
50
  }
55
- };
56
- exports.setKnownMicroservicesHandler = setKnownMicroservicesHandler;
57
- const getKnownMicroservicesHandler = () => (req, res) => {
51
+ }
52
+ async function deleteConversation(req, res) {
58
53
  try {
59
- const microservices = (0, _knownMicroservices.getKnownMicroservices)();
60
- res.json({
61
- knownMicroservices: microservices
54
+ const {
55
+ conversationId
56
+ } = req.params;
57
+ const deleted = (0, _aiService.getAiService)().deleteConversation(conversationId);
58
+ if (!deleted) {
59
+ res.status(404).json({
60
+ error: 'Not found'
61
+ });
62
+ return;
63
+ }
64
+ res.status(204).send();
65
+ } catch (err) {
66
+ res.status(500).json({
67
+ error: err.message
62
68
  });
63
- } catch (error) {
64
- _logger.default.error(error);
69
+ }
70
+ }
71
+ async function sendMessage(req, res) {
72
+ try {
73
+ const {
74
+ conversationId
75
+ } = req.params;
76
+ const {
77
+ content
78
+ } = req.body;
79
+ if (!content) {
80
+ res.status(400).json({
81
+ error: 'Missing content'
82
+ });
83
+ return;
84
+ }
85
+ const messages = await (0, _aiService.getAiService)().sendMessage(conversationId, content);
86
+ res.json(messages);
87
+ } catch (err) {
65
88
  res.status(500).json({
66
- error: 'Internal error'
89
+ error: err.message
67
90
  });
68
91
  }
69
- };
70
- exports.getKnownMicroservicesHandler = getKnownMicroservicesHandler;
92
+ }
@@ -6,11 +6,18 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.getAIRoutes = void 0;
7
7
  var _express = require("express");
8
8
  var _aiController = require("./aiController.cjs");
9
+ var _aiService = require("./aiService.cjs");
9
10
  const getAIRoutes = oasTlmConfig => {
10
11
  const router = (0, _express.Router)();
11
- router.post('/chat', (0, _aiController.answerQuestion)(oasTlmConfig));
12
- router.post('/microservices', (0, _aiController.setKnownMicroservicesHandler)());
13
- router.get('/microservices', (0, _aiController.getKnownMicroservicesHandler)());
12
+ (0, _aiService.configureAiService)(oasTlmConfig); //oasTlmConfig.ai.openAIKey
13
+ router.get('/chat/health', (req, res) => {
14
+ res.status(200).send('AI service is healthy');
15
+ });
16
+ router.get('/chat', _aiController.listConversations);
17
+ router.post('/chat', _aiController.createConversation);
18
+ router.get('/chat/:conversationId', _aiController.getConversationHistory);
19
+ router.post('/chat/:conversationId/message', _aiController.sendMessage);
20
+ router.delete('/chat/:conversationId', _aiController.deleteConversation);
14
21
  return router;
15
22
  };
16
23
  exports.getAIRoutes = getAIRoutes;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.configureAiService = configureAiService;
7
+ exports.getAiService = getAiService;
8
+ var _openai = _interopRequireDefault(require("openai"));
9
+ var _agent = require("./agent.cjs");
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ class AIService {
12
+ constructor(config) {
13
+ this.config = config;
14
+ this.conversations = new Map();
15
+ this.openai = new _openai.default({
16
+ apiKey: this.config.apiKey
17
+ });
18
+ this.model = config.model;
19
+ this.extraPrompts = config.extraPrompts || [];
20
+ }
21
+ createConversation() {
22
+ const id = Math.random().toString(36).substring(2, 15);
23
+ const conversation = {
24
+ id,
25
+ messages: []
26
+ };
27
+ this.conversations.set(id, conversation);
28
+ return conversation;
29
+ }
30
+ listConversations() {
31
+ return Array.from(this.conversations.values());
32
+ }
33
+ getConversation(id) {
34
+ return this.conversations.get(id);
35
+ }
36
+ deleteConversation(id) {
37
+ return this.conversations.delete(id);
38
+ }
39
+ async sendMessage(conversationId, content, model) {
40
+ const conversation = this.conversations.get(conversationId);
41
+ if (!conversation) throw new Error('Conversation not found');
42
+ conversation.messages.push({
43
+ role: 'system',
44
+ timestamp: new Date().toISOString(),
45
+ content: "This is a telemetry chat. Focus your replies strictly on the topics and instructions defined by the system prompts and the available tools. Do not answer outside of these boundaries. Reply in the same language as the question."
46
+ });
47
+ if (this.extraPrompts.length > 0) {
48
+ this.extraPrompts.forEach(prompt => {
49
+ conversation.messages.push({
50
+ role: 'system',
51
+ content: prompt,
52
+ timestamp: new Date().toISOString()
53
+ });
54
+ });
55
+ }
56
+ conversation.messages.push({
57
+ role: 'user',
58
+ content,
59
+ timestamp: new Date().toISOString()
60
+ });
61
+ // Set conversation name if not set
62
+ if (!('name' in conversation) || !conversation.name) {
63
+ conversation.name = content.slice(0, 30);
64
+ }
65
+ // Use the agent function with tools
66
+ // Internaly pushes new messages to conversation.messages
67
+ const currentMessagesCount = conversation.messages.length;
68
+ await (0, _agent.agent)(this.openai, conversation.messages, model || this.model, this.extraPrompts);
69
+ // Return the last assistant message (the one just added by agent)
70
+ const generatedMessages = conversation.messages.slice(currentMessagesCount);
71
+ return generatedMessages;
72
+ }
73
+ listConversationsMinimal() {
74
+ return Array.from(this.conversations.values()).map(c => ({
75
+ id: c.id,
76
+ name: c.name
77
+ }));
78
+ }
79
+ async listModels() {
80
+ const {
81
+ data
82
+ } = await this.openai.models.list();
83
+ return data.map(m => m.id).sort();
84
+ }
85
+ async isValidModel(modelId) {
86
+ try {
87
+ await this.openai.models.retrieve(modelId);
88
+ return true;
89
+ } catch {
90
+ return false;
91
+ }
92
+ }
93
+ }
94
+ let aiService;
95
+ function configureAiService(config) {
96
+ const openAIKey = config.ai?.openAIKey;
97
+ const model = config.ai.openAIModel;
98
+ const extraPrompts = config.ai.extraContextPrompts;
99
+ if (!openAIKey) throw new Error('OpenAI API key is required');
100
+ aiService = new AIService({
101
+ apiKey: openAIKey,
102
+ model,
103
+ extraPrompts
104
+ });
105
+ }
106
+ function getAiService() {
107
+ if (!aiService) throw new Error('AI Service not configured');
108
+ return aiService;
109
+ }
@@ -4,9 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.tools = exports.availableTools = void 0;
7
- var _axios = _interopRequireDefault(require("axios"));
8
7
  var _logger = _interopRequireDefault(require("../utils/logger.cjs"));
9
- var _knownMicroservices = require("./knownMicroservices.cjs");
10
8
  var _telemetryRegistry = require("../telemetry/telemetryRegistry.cjs");
11
9
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
10
  const getTraces = async searchInput => {
@@ -32,31 +30,22 @@ const getTraces = async searchInput => {
32
30
  const getLogs = async (startDate, endDate) => {
33
31
  _logger.default.debug("getLogs called with startDate:", startDate, "endDate:", endDate);
34
32
  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
- _telemetryRegistry.inMemoryDbLogExporter.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
- });
33
+ // Timestamps are stored in microseconds in the DB (must multiply by 1000)
34
+ const startEpoch = startDate ? new Date(startDate).getTime() * 1000 : 0;
35
+ const endEpoch = endDate ? new Date(endDate).getTime() * 1000 : Date.now() * 1000;
36
+ _logger.default.debug(`Fetching logs from ${startEpoch} to ${endEpoch}`);
37
+ const nedbQuery = {
38
+ timestamp: {
39
+ $gte: startEpoch,
40
+ $lte: endEpoch
41
+ }
42
+ };
43
+ const logs = (await _telemetryRegistry.inMemoryDbLogExporter.find({
44
+ query: nedbQuery,
45
+ messageSearch: null,
46
+ limit: 50 // or any appropriate limit
47
+ })) || [];
48
+ _logger.default.debug(`Found ${logs.length} logs in the specified range.`);
60
49
  const simplifiedLogs = getSimplifiedLogs(logs);
61
50
  return {
62
51
  logs: simplifiedLogs
@@ -66,34 +55,6 @@ const getLogs = async (startDate, endDate) => {
66
55
  throw error;
67
56
  }
68
57
  };
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
- _telemetryRegistry.inMemoryDbMetricExporter.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
58
  const startTelemetry = () => {
98
59
  _logger.default.debug("Starting telemetry...");
99
60
  _telemetryRegistry.inMemoryDbSpanExporter.enable();
@@ -120,29 +81,13 @@ const getTelemetryStatus = () => {
120
81
  metricsEnabled: _telemetryRegistry.inMemoryDbMetricExporter.isEnabled()
121
82
  };
122
83
  };
123
- const talkToExternalMicroserviceAgent = async (message, microserviceId) => {
124
- _logger.default.debug("talkToExternalMicroserviceAgent called with question:", message, "microservice:", microserviceId);
125
- const knownMicroservices = (0, _knownMicroservices.getKnownMicroservices)();
126
- const identifiedMicroservice = knownMicroservices.find(m => m.id === microserviceId);
127
- if (!identifiedMicroservice) {
128
- _logger.default.error(`Agent tried to call an unknown microservice: ${microserviceId}, available microservices: ${knownMicroservices.map(m => m.id).join(', ')}`);
129
- return {
130
- microservice: microserviceId,
131
- response: `I cannot help with that. The microservice ${microserviceId} is not recognized. Available microservices are: ${knownMicroservices.map(m => m.id).join(', ')}`
132
- };
133
- }
134
- const microserviceResponse = await _axios.default.post(identifiedMicroservice.url, {
135
- question: message
136
- });
84
+ const getCurrentDate = () => {
85
+ _logger.default.debug("Getting the current date in ISO format...");
86
+ const now = new Date();
137
87
  return {
138
- microservice: microserviceId,
139
- response: microserviceResponse.data
88
+ currentDateISO: now.toISOString()
140
89
  };
141
90
  };
142
- const getMicroserviceAgents = () => {
143
- _logger.default.debug("Getting microservice agents...");
144
- return (0, _knownMicroservices.getKnownMicroservices)();
145
- };
146
91
  const tools = exports.tools = [{
147
92
  type: "function",
148
93
  function: {
@@ -231,7 +176,8 @@ const tools = exports.tools = [{
231
176
  description: `Fetches log data for the microservice.
232
177
  Logs provide information about system events, including timestamps, log levels (e.g., info, error), and messages.
233
178
  The 'startDate' and 'endDate' parameters define the time range for fetching logs.
234
- If don't provide a range, all logs will be fetched. Providing a specific range improves performance.
179
+ If you need a date, you MUST first call the "getCurrentDate" tool to obtain the current date in ISO format, and then use it as a parameter.
180
+ If you don't provide a range, all logs will be fetched. Providing a specific range improves performance.
235
181
  Example 'startDate' and 'endDate':
236
182
  {
237
183
  "startDate": "2023-10-01T00:00:00Z",
@@ -250,54 +196,6 @@ const tools = exports.tools = [{
250
196
  }
251
197
  }
252
198
  }
253
- }, {
254
- type: "function",
255
- function: {
256
- name: "getMetrics",
257
- description: `Fetches metrics data for the microservice.
258
- Metrics provide performance-related data, such as CPU usage, memory usage, and process-specific metrics.
259
- The 'searchInput' parameter is an object used to filter metrics based on specific criteria.
260
- This is a NeDB query using MongoDB-like (NeDB) syntax. If 'searchInput' is null, all metrics will be fetched. Providing specific filters improves performance.
261
-
262
- Example 'searchInput':
263
- {
264
- "timestamp": { "$gte": 1747651105757, "$lte": 1747651200935 }
265
- }
266
-
267
- Common filters include timestamps.`,
268
- parameters: {
269
- type: "object",
270
- properties: {
271
- searchInput: {
272
- type: "object",
273
- description: `Optional search criteria for filtering metrics.
274
- This is a NeDB query using MongoDB-like (NeDB) syntax.
275
- For example, you can filter by timestamps.
276
- If null, all metrics will be returned.`,
277
- properties: {
278
- "timestamp": {
279
- type: "object",
280
- properties: {
281
- "$gte": {
282
- type: "integer"
283
- },
284
- "$lte": {
285
- type: "integer"
286
- }
287
- }
288
- },
289
- "cpuUsageData.cpuNumber": {
290
- type: "string"
291
- },
292
- "memoryData.used": {
293
- type: "integer"
294
- }
295
- }
296
- }
297
- },
298
- required: ["searchInput"]
299
- }
300
- }
301
199
  }, {
302
200
  type: "function",
303
201
  function: {
@@ -333,158 +231,21 @@ const tools = exports.tools = [{
333
231
  }, {
334
232
  type: "function",
335
233
  function: {
336
- name: "getCurrentTimestampInEpoch",
337
- description: `Retrieves the current timestamp in epoch format (miliseconds or seconds).
338
- 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.`,
339
- parameters: {}
340
- }
341
- }, {
342
- type: "function",
343
- function: {
344
- name: "talkToExternalMicroserviceAgent",
345
- description: `Use this function to communicate with external microservice agent.
346
- if you want to talk to a microservice agent, you must provide the message and the microservice you want to talk to.
347
- When you call this function, it will send the message to the specified microservice and return the response.
348
-
349
- Example 'message':
350
- {
351
- "message": "What is the status of the service?",
352
- "microservice": "Reporter"
353
- }
354
-
355
- Microservices Availables (by ID):
356
- ${(0, _knownMicroservices.getKnownMicroservices)().map(m => m.id).join(", ")}
357
- `,
358
- parameters: {
359
- type: "object",
360
- properties: {
361
- message: {
362
- type: "string",
363
- description: `The message to be sent to the external microservice agent.`
364
- },
365
- microservice: {
366
- type: "string"
367
- }
368
- },
369
- required: ["message", "microservice"]
370
- }
371
- }
372
- }, {
373
- type: "function",
374
- function: {
375
- name: "getMicroserviceAgents",
376
- description: `Retrieves the list of available microservice agents.
377
- This function provides information about the microservices that can be communicated with.`,
234
+ name: "getCurrentDate",
235
+ description: `Returns the current date in ISO 8601 format (e.g., "2024-06-07T12:34:56.789Z").
236
+ Use this tool to obtain the current date when you need to specify a date for other tools, such as "getLogs".`,
378
237
  parameters: {}
379
238
  }
380
239
  }];
381
240
  const availableTools = exports.availableTools = {
382
241
  getTraces,
383
242
  getLogs,
384
- getMetrics,
385
243
  startTelemetry,
386
244
  stopTelemetry,
387
245
  resetTelemetry,
388
246
  getTelemetryStatus,
389
- getCurrentTimestampInEpoch,
390
- talkToExternalMicroserviceAgent,
391
- getMicroserviceAgents
247
+ getCurrentDate
392
248
  };
393
- function getSimplifiedMetrics(metrics) {
394
- return metrics.map(resourceMetric => {
395
- const serviceName = resourceMetric.resource?._memoizedAttributes?.service?.name || 'unknown-service';
396
- const cpuUtilization = {};
397
- let cpuCount = 0;
398
- const memoryUsageMB = {
399
- used: 0,
400
- free: 0
401
- };
402
- const memoryUtilizationPercent = {
403
- used: 0,
404
- free: 0
405
- };
406
- const networkIO = {
407
- transmit: 0,
408
- receive: 0
409
- };
410
- const processCPU = {};
411
- let processMemoryUsage = 0;
412
- for (const scopeMetric of resourceMetric.scopeMetrics) {
413
- for (const metric of scopeMetric.metrics) {
414
- const name = metric.descriptor.name;
415
- if (name === 'system.cpu.utilization') {
416
- const stateSums = {};
417
- const stateCounts = {};
418
- for (const dp of metric.dataPoints) {
419
- const state = dp.attributes?.system?.cpu?.state;
420
- if (!state) continue;
421
- // @ts-expect-error index signature
422
- stateSums[state] = (stateSums[state] || 0) + dp.value;
423
- // @ts-expect-error index signature
424
- stateCounts[state] = (stateCounts[state] || 0) + 1;
425
- }
426
- for (const state in stateSums) {
427
- // @ts-expect-error index signature
428
- cpuUtilization[state] = stateSums[state] / stateCounts[state];
429
- }
430
- cpuCount = Math.max(...metric.dataPoints.map(dp => parseInt(dp.attributes?.system?.cpu?.logical_number || 0, 10))) + 1;
431
- }
432
- if (name === 'system.memory.usage') {
433
- for (const dp of metric.dataPoints) {
434
- const state = dp.attributes?.system?.memory?.state;
435
- // @ts-expect-error index signature
436
- if (state) memoryUsageMB[state] = dp.value;
437
- }
438
- }
439
- if (name === 'system.memory.utilization') {
440
- for (const dp of metric.dataPoints) {
441
- const state = dp.attributes?.system?.memory?.state;
442
- // @ts-expect-error index signature
443
- if (state) memoryUtilizationPercent[state] = dp.value;
444
- }
445
- }
446
- if (name === 'system.network.io') {
447
- for (const dp of metric.dataPoints) {
448
- const direction = dp.attributes?.network?.io?.direction;
449
- // @ts-expect-error index signature
450
- if (direction) networkIO[direction] += dp.value;
451
- }
452
- }
453
- if (name === 'process.cpu.time') {
454
- for (const dp of metric.dataPoints) {
455
- const state = dp.attributes?.process?.cpu?.state;
456
- // @ts-expect-error index signature
457
- if (state) processCPU[state] = dp.value;
458
- }
459
- }
460
- if (name === 'process.memory.usage') {
461
- processMemoryUsage = metric.dataPoints[0]?.value || 0;
462
- }
463
- }
464
- }
465
- return {
466
- service: serviceName,
467
- cpu: {
468
- avgUtilization: cpuUtilization,
469
- cores: cpuCount
470
- },
471
- memory: {
472
- usedGB: (memoryUsageMB.used || 0) / 1024 ** 3,
473
- freeGB: (memoryUsageMB.free || 0) / 1024 ** 3,
474
- usedPercent: (memoryUtilizationPercent.used || 0) * 100,
475
- freePercent: (1 - (memoryUtilizationPercent.used || 0)) * 100
476
- },
477
- network: {
478
- transmittedMB: networkIO.transmit / 1024 ** 2,
479
- receivedMB: networkIO.receive / 1024 ** 2
480
- },
481
- process: {
482
- cpuTimeSec: processCPU,
483
- memoryUsageMB: processMemoryUsage / 1024 ** 2
484
- }
485
- };
486
- });
487
- }
488
249
  function getSimplifiedTraces(spans) {
489
250
  return spans.map(span => {
490
251
  return {
@@ -502,10 +263,11 @@ function getSimplifiedTraces(spans) {
502
263
  function getSimplifiedLogs(logs) {
503
264
  return logs.map(log => ({
504
265
  service: log.resource?.attributes?.service?.name || undefined,
505
- timestamp: log.timestamp,
266
+ timestamp: new Date(log.timestamp / 1000).toISOString(),
267
+ // converting microseconds to milliseconds
268
+ severityText: log.severityText,
506
269
  message: log.body,
507
270
  traceId: log.traceId,
508
- spanId: log.spanId,
509
- source: log.attributes?.source?.source || undefined
271
+ source: log.attributes?.source || undefined
510
272
  }));
511
273
  }