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