@forgehive/hive-sdk 0.1.6 → 0.2.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.
- package/README.md +318 -528
- package/dist/index.d.ts +0 -2
- package/dist/index.js +10 -66
- package/dist/test/metadata.test.js +123 -171
- package/dist/test/sendLog.test.js +199 -117
- package/package.json +1 -1
- package/src/index.ts +11 -78
- package/src/test/metadata.test.ts +143 -218
- package/src/test/sendLog.test.ts +237 -145
- package/src/test/sendLogByUuid.test.ts +0 -272
package/dist/index.d.ts
CHANGED
|
@@ -61,13 +61,11 @@ export declare class HiveLogClient {
|
|
|
61
61
|
}>;
|
|
62
62
|
private mergeMetadata;
|
|
63
63
|
sendLog(record: ExecutionRecord, metadata?: Metadata): Promise<'success' | 'error' | 'silent' | LogApiSuccess>;
|
|
64
|
-
sendLogByUuid(record: ExecutionRecord, taskUuid: string, metadata?: Metadata): Promise<'success' | 'error' | 'silent' | LogApiSuccess>;
|
|
65
64
|
getListener(): (record: ExecutionRecord) => Promise<void>;
|
|
66
65
|
getLog(taskName: string, uuid: string): Promise<LogApiResult | null>;
|
|
67
66
|
setQuality(taskName: string, uuid: string, quality: Quality): Promise<boolean>;
|
|
68
67
|
private loadForgeConfig;
|
|
69
68
|
private getTaskUUID;
|
|
70
|
-
sendLogByName(taskName: string, record: ExecutionRecord, metadata?: Metadata): Promise<'success' | 'error' | 'silent' | LogApiSuccess>;
|
|
71
69
|
}
|
|
72
70
|
export declare const createHiveLogClient: (config: HiveLogClientConfig) => HiveLogClient;
|
|
73
71
|
export interface HiveClientConfig {
|
package/dist/index.js
CHANGED
|
@@ -169,55 +169,19 @@ class HiveLogClient {
|
|
|
169
169
|
log('Silent mode: Skipping sendLog for task "%s" - client not initialized', taskName);
|
|
170
170
|
return 'silent';
|
|
171
171
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
try {
|
|
175
|
-
const logsUrl = `${this.host}/api/tasks/log-ingest`;
|
|
176
|
-
log('Sending log for task "%s" to %s', taskName, logsUrl);
|
|
177
|
-
const authToken = `${this.apiKey}:${this.apiSecret}`;
|
|
178
|
-
// Merge metadata with priority: sendLog > record.metadata > client
|
|
179
|
-
const finalMetadata = this.mergeMetadata(record, metadata);
|
|
180
|
-
// Create logItem with merged metadata (no UUID generation for legacy method)
|
|
181
|
-
const logItem = {
|
|
182
|
-
...record,
|
|
183
|
-
taskName,
|
|
184
|
-
metadata: finalMetadata
|
|
185
|
-
};
|
|
186
|
-
const response = await axios_1.default.post(logsUrl, {
|
|
187
|
-
projectName: this.projectName,
|
|
188
|
-
taskName,
|
|
189
|
-
logItem: JSON.stringify(logItem)
|
|
190
|
-
}, {
|
|
191
|
-
headers: {
|
|
192
|
-
Authorization: `Bearer ${authToken}`,
|
|
193
|
-
'Content-Type': 'application/json'
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
log('Success: Sent log for task "%s"', taskName);
|
|
197
|
-
// Return the full response data if available
|
|
198
|
-
if (response.data && typeof response.data === 'object' && 'uuid' in response.data) {
|
|
199
|
-
return response.data;
|
|
200
|
-
}
|
|
201
|
-
return 'success';
|
|
202
|
-
}
|
|
203
|
-
catch (e) {
|
|
204
|
-
const error = e;
|
|
205
|
-
log('Error: Failed to send log for task "%s": %s', taskName, error.message);
|
|
172
|
+
if (!this.projectUuid) {
|
|
173
|
+
log('Error: sendLog requires projectUuid to be set in client config');
|
|
206
174
|
return 'error';
|
|
207
175
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
if (!
|
|
211
|
-
log('
|
|
212
|
-
return 'silent';
|
|
213
|
-
}
|
|
214
|
-
if (!this.projectUuid) {
|
|
215
|
-
log('Error: sendLogByUuid requires projectUuid to be set in client config');
|
|
176
|
+
// Look up task UUID from forge.json
|
|
177
|
+
const taskUuid = this.getTaskUUID(taskName);
|
|
178
|
+
if (!taskUuid) {
|
|
179
|
+
log('Error: Cannot find UUID for task "%s" in forge.json', taskName);
|
|
216
180
|
return 'error';
|
|
217
181
|
}
|
|
218
182
|
try {
|
|
219
183
|
const logsUrl = `${this.host}/api/log-ingest`;
|
|
220
|
-
log('Sending log for task
|
|
184
|
+
log('Sending log for task "%s" (UUID: %s) to %s', taskName, taskUuid, logsUrl);
|
|
221
185
|
const authToken = `${this.apiKey}:${this.apiSecret}`;
|
|
222
186
|
// Merge metadata with priority: sendLog > record.metadata > client
|
|
223
187
|
const finalMetadata = this.mergeMetadata(record, metadata);
|
|
@@ -227,19 +191,17 @@ class HiveLogClient {
|
|
|
227
191
|
uuid: record.uuid || (0, uuid_1.v7)(),
|
|
228
192
|
metadata: finalMetadata
|
|
229
193
|
};
|
|
230
|
-
// Create logItem with merged metadata and UUID
|
|
231
|
-
const logItem = recordWithUuid;
|
|
232
194
|
const response = await axios_1.default.post(logsUrl, {
|
|
233
195
|
projectUuid: this.projectUuid,
|
|
234
196
|
taskUuid,
|
|
235
|
-
logItem: JSON.stringify(
|
|
197
|
+
logItem: JSON.stringify(recordWithUuid)
|
|
236
198
|
}, {
|
|
237
199
|
headers: {
|
|
238
200
|
Authorization: `Bearer ${authToken}`,
|
|
239
201
|
'Content-Type': 'application/json'
|
|
240
202
|
}
|
|
241
203
|
});
|
|
242
|
-
log('Success: Sent log for task UUID
|
|
204
|
+
log('Success: Sent log for task "%s" (UUID: %s)', taskName, taskUuid);
|
|
243
205
|
// Return the full response data if available
|
|
244
206
|
if (response.data && typeof response.data === 'object' && 'uuid' in response.data) {
|
|
245
207
|
return response.data;
|
|
@@ -248,7 +210,7 @@ class HiveLogClient {
|
|
|
248
210
|
}
|
|
249
211
|
catch (e) {
|
|
250
212
|
const error = e;
|
|
251
|
-
log('Error: Failed to send log for task
|
|
213
|
+
log('Error: Failed to send log for task "%s": %s', taskName, error.message);
|
|
252
214
|
return 'error';
|
|
253
215
|
}
|
|
254
216
|
}
|
|
@@ -335,24 +297,6 @@ class HiveLogClient {
|
|
|
335
297
|
log('Found UUID "%s" for task "%s"', task.uuid, taskName);
|
|
336
298
|
return task.uuid;
|
|
337
299
|
}
|
|
338
|
-
async sendLogByName(taskName, record, metadata) {
|
|
339
|
-
if (!this.isInitialized) {
|
|
340
|
-
log('Silent mode: Skipping sendLogByName for task "%s" - client not initialized', taskName);
|
|
341
|
-
return 'silent';
|
|
342
|
-
}
|
|
343
|
-
if (!this.projectUuid) {
|
|
344
|
-
log('Error: sendLogByName requires projectUuid to be set in client config');
|
|
345
|
-
return 'error';
|
|
346
|
-
}
|
|
347
|
-
const taskUuid = this.getTaskUUID(taskName);
|
|
348
|
-
if (!taskUuid) {
|
|
349
|
-
log('Error: Cannot find UUID for task "%s" in forge.json', taskName);
|
|
350
|
-
return 'error';
|
|
351
|
-
}
|
|
352
|
-
// Use the existing sendLogByUuid method
|
|
353
|
-
log('Sending log for task "%s" with uuid "%s"', taskName, taskUuid);
|
|
354
|
-
return await this.sendLogByUuid(record, taskUuid, metadata);
|
|
355
|
-
}
|
|
356
300
|
}
|
|
357
301
|
exports.HiveLogClient = HiveLogClient;
|
|
358
302
|
const createHiveLogClient = (config) => {
|
|
@@ -4,18 +4,44 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const axios_1 = __importDefault(require("axios"));
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
8
|
const index_1 = require("../index");
|
|
8
|
-
// Mock axios
|
|
9
|
+
// Mock axios and fs
|
|
9
10
|
jest.mock('axios');
|
|
11
|
+
jest.mock('fs');
|
|
10
12
|
const mockedAxios = axios_1.default;
|
|
13
|
+
const mockedFs = fs_1.default;
|
|
11
14
|
describe('HiveLogClient Metadata', () => {
|
|
12
15
|
const testConfig = {
|
|
13
16
|
projectName: 'test-project',
|
|
17
|
+
projectUuid: '550e8400-e29b-41d4-a716-446655440000',
|
|
14
18
|
apiKey: 'test-api-key',
|
|
15
19
|
apiSecret: 'test-api-secret',
|
|
16
|
-
host: 'https://test-host.com'
|
|
20
|
+
host: 'https://test-host.com',
|
|
21
|
+
forgeConfigPath: './forge.json'
|
|
22
|
+
};
|
|
23
|
+
const mockForgeConfig = {
|
|
24
|
+
project: {
|
|
25
|
+
name: 'test-project',
|
|
26
|
+
uuid: '550e8400-e29b-41d4-a716-446655440000'
|
|
27
|
+
},
|
|
28
|
+
tasks: {
|
|
29
|
+
'test-task': {
|
|
30
|
+
path: 'src/tasks/test.ts',
|
|
31
|
+
handler: 'testTask',
|
|
32
|
+
uuid: 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
|
|
33
|
+
},
|
|
34
|
+
'search-task': {
|
|
35
|
+
path: 'src/tasks/search.ts',
|
|
36
|
+
handler: 'searchTask',
|
|
37
|
+
uuid: 'a45aafe3-8b01-4b58-b15d-9a96274858ee'
|
|
38
|
+
}
|
|
39
|
+
}
|
|
17
40
|
};
|
|
18
41
|
beforeEach(() => {
|
|
42
|
+
// Mock fs
|
|
43
|
+
mockedFs.existsSync.mockReturnValue(true);
|
|
44
|
+
mockedFs.readFileSync.mockReturnValue(JSON.stringify(mockForgeConfig));
|
|
19
45
|
// Clear all mocks
|
|
20
46
|
jest.clearAllMocks();
|
|
21
47
|
});
|
|
@@ -64,6 +90,7 @@ describe('HiveLogClient Metadata', () => {
|
|
|
64
90
|
let client;
|
|
65
91
|
beforeEach(() => {
|
|
66
92
|
client = new index_1.HiveLogClient(testConfig);
|
|
93
|
+
jest.clearAllMocks();
|
|
67
94
|
});
|
|
68
95
|
it('should send log without metadata parameter', async () => {
|
|
69
96
|
mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
|
|
@@ -77,23 +104,21 @@ describe('HiveLogClient Metadata', () => {
|
|
|
77
104
|
};
|
|
78
105
|
const result = await client.sendLog(executionRecord);
|
|
79
106
|
expect(result).toBe('success');
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
});
|
|
107
|
+
// Verify it uses the UUID endpoint
|
|
108
|
+
const callArgs = mockedAxios.post.mock.calls[0];
|
|
109
|
+
expect(callArgs[0]).toBe('https://test-host.com/api/log-ingest');
|
|
110
|
+
// Verify request body structure
|
|
111
|
+
const requestBody = callArgs[1];
|
|
112
|
+
expect(requestBody.projectUuid).toBe(testConfig.projectUuid);
|
|
113
|
+
expect(requestBody.taskUuid).toBe('f47ac10b-58cc-4372-a567-0e02b2c3d479');
|
|
114
|
+
// Parse and verify logItem
|
|
115
|
+
const logItem = JSON.parse(requestBody.logItem);
|
|
116
|
+
expect(logItem.uuid).toBeDefined();
|
|
117
|
+
expect(logItem.input).toBe('test-input');
|
|
118
|
+
expect(logItem.output).toBe('test-output');
|
|
119
|
+
expect(logItem.taskName).toBe('test-task');
|
|
120
|
+
expect(logItem.type).toBe('success');
|
|
121
|
+
expect(logItem.metadata).toEqual({});
|
|
97
122
|
});
|
|
98
123
|
it('should send log with metadata parameter', async () => {
|
|
99
124
|
mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
|
|
@@ -111,25 +136,13 @@ describe('HiveLogClient Metadata', () => {
|
|
|
111
136
|
};
|
|
112
137
|
const result = await client.sendLog(executionRecord, metadata);
|
|
113
138
|
expect(result).toBe('success');
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
type: 'success',
|
|
122
|
-
boundaries: {},
|
|
123
|
-
metadata: {
|
|
124
|
-
requestId: 'req-123',
|
|
125
|
-
userId: 'user-456'
|
|
126
|
-
}
|
|
127
|
-
})
|
|
128
|
-
}, {
|
|
129
|
-
headers: {
|
|
130
|
-
Authorization: 'Bearer test-api-key:test-api-secret',
|
|
131
|
-
'Content-Type': 'application/json'
|
|
132
|
-
}
|
|
139
|
+
const callArgs = mockedAxios.post.mock.calls[0];
|
|
140
|
+
expect(callArgs[0]).toBe('https://test-host.com/api/log-ingest');
|
|
141
|
+
const requestBody = callArgs[1];
|
|
142
|
+
const logItem = JSON.parse(requestBody.logItem);
|
|
143
|
+
expect(logItem.metadata).toEqual({
|
|
144
|
+
requestId: 'req-123',
|
|
145
|
+
userId: 'user-456'
|
|
133
146
|
});
|
|
134
147
|
});
|
|
135
148
|
it('should handle logItem with only input property', async () => {
|
|
@@ -137,34 +150,22 @@ describe('HiveLogClient Metadata', () => {
|
|
|
137
150
|
const metadata = { type: 'minimal' };
|
|
138
151
|
const result = await client.sendLog({ input: 'simple input', taskName: 'test-task', type: 'success', boundaries: {}, metadata: {} }, metadata);
|
|
139
152
|
expect(result).toBe('success');
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
taskName: 'test-task',
|
|
146
|
-
type: 'success',
|
|
147
|
-
boundaries: {},
|
|
148
|
-
metadata: { type: 'minimal' }
|
|
149
|
-
})
|
|
150
|
-
}, expect.any(Object));
|
|
153
|
+
const callArgs = mockedAxios.post.mock.calls[0];
|
|
154
|
+
const requestBody = callArgs[1];
|
|
155
|
+
const logItem = JSON.parse(requestBody.logItem);
|
|
156
|
+
expect(logItem.input).toBe('simple input');
|
|
157
|
+
expect(logItem.metadata).toEqual({ type: 'minimal' });
|
|
151
158
|
});
|
|
152
159
|
it('should handle logItem with null input values', async () => {
|
|
153
160
|
mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
|
|
154
161
|
const metadata = { type: 'null-test' };
|
|
155
162
|
const result = await client.sendLog({ input: null, taskName: 'test-task', type: 'success', boundaries: {}, metadata: {} }, metadata);
|
|
156
163
|
expect(result).toBe('success');
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
taskName: 'test-task',
|
|
163
|
-
type: 'success',
|
|
164
|
-
boundaries: {},
|
|
165
|
-
metadata: { type: 'null-test' }
|
|
166
|
-
})
|
|
167
|
-
}, expect.any(Object));
|
|
164
|
+
const callArgs = mockedAxios.post.mock.calls[0];
|
|
165
|
+
const requestBody = callArgs[1];
|
|
166
|
+
const logItem = JSON.parse(requestBody.logItem);
|
|
167
|
+
expect(logItem.input).toBeNull();
|
|
168
|
+
expect(logItem.metadata).toEqual({ type: 'null-test' });
|
|
168
169
|
});
|
|
169
170
|
});
|
|
170
171
|
describe('Metadata priority system', () => {
|
|
@@ -175,23 +176,16 @@ describe('HiveLogClient Metadata', () => {
|
|
|
175
176
|
version: '1.0.0'
|
|
176
177
|
};
|
|
177
178
|
const client = new index_1.HiveLogClient({ ...testConfig, metadata: baseMetadata });
|
|
179
|
+
jest.clearAllMocks();
|
|
178
180
|
const logItem = { input: 'test' };
|
|
179
181
|
await client.sendLog({ ...logItem, taskName: 'test-task', type: 'success', boundaries: {}, metadata: {} });
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
version: '1.0.0'
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
|
|
191
|
-
projectName: 'test-project',
|
|
192
|
-
taskName: 'test-task',
|
|
193
|
-
logItem: JSON.stringify(expectedLogItem)
|
|
194
|
-
}, expect.any(Object));
|
|
182
|
+
const callArgs = mockedAxios.post.mock.calls[0];
|
|
183
|
+
const requestBody = callArgs[1];
|
|
184
|
+
const parsedLogItem = JSON.parse(requestBody.logItem);
|
|
185
|
+
expect(parsedLogItem.metadata).toEqual({
|
|
186
|
+
environment: 'production',
|
|
187
|
+
version: '1.0.0'
|
|
188
|
+
});
|
|
195
189
|
});
|
|
196
190
|
it('should merge logItem metadata with base metadata', async () => {
|
|
197
191
|
mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
|
|
@@ -200,6 +194,7 @@ describe('HiveLogClient Metadata', () => {
|
|
|
200
194
|
version: '1.0.0'
|
|
201
195
|
};
|
|
202
196
|
const client = new index_1.HiveLogClient({ ...testConfig, metadata: baseMetadata });
|
|
197
|
+
jest.clearAllMocks();
|
|
203
198
|
const logItem = {
|
|
204
199
|
input: 'test',
|
|
205
200
|
metadata: {
|
|
@@ -208,22 +203,14 @@ describe('HiveLogClient Metadata', () => {
|
|
|
208
203
|
}
|
|
209
204
|
};
|
|
210
205
|
await client.sendLog({ ...logItem, taskName: 'test-task', type: 'success', boundaries: {}, metadata: logItem.metadata || {} });
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
type: 'success',
|
|
220
|
-
boundaries: {}
|
|
221
|
-
};
|
|
222
|
-
expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
|
|
223
|
-
projectName: 'test-project',
|
|
224
|
-
taskName: 'test-task',
|
|
225
|
-
logItem: JSON.stringify(expectedLogItem)
|
|
226
|
-
}, expect.any(Object));
|
|
206
|
+
const callArgs = mockedAxios.post.mock.calls[0];
|
|
207
|
+
const requestBody = callArgs[1];
|
|
208
|
+
const parsedLogItem = JSON.parse(requestBody.logItem);
|
|
209
|
+
expect(parsedLogItem.metadata).toEqual({
|
|
210
|
+
environment: 'production', // from base
|
|
211
|
+
version: '1.1.0', // from logItem (overrides base)
|
|
212
|
+
sessionId: 'session-123' // from logItem
|
|
213
|
+
});
|
|
227
214
|
});
|
|
228
215
|
it('should give sendLog metadata highest priority', async () => {
|
|
229
216
|
mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
|
|
@@ -233,6 +220,7 @@ describe('HiveLogClient Metadata', () => {
|
|
|
233
220
|
priority: 'base'
|
|
234
221
|
};
|
|
235
222
|
const client = new index_1.HiveLogClient({ ...testConfig, metadata: baseMetadata });
|
|
223
|
+
jest.clearAllMocks();
|
|
236
224
|
const logItem = {
|
|
237
225
|
input: 'test',
|
|
238
226
|
metadata: {
|
|
@@ -247,24 +235,16 @@ describe('HiveLogClient Metadata', () => {
|
|
|
247
235
|
priority: 'sendLog'
|
|
248
236
|
};
|
|
249
237
|
await client.sendLog({ ...logItem, taskName: 'test-task', type: 'success', boundaries: {}, metadata: logItem.metadata || {} }, sendLogMetadata);
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
type: 'success',
|
|
261
|
-
boundaries: {}
|
|
262
|
-
};
|
|
263
|
-
expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
|
|
264
|
-
projectName: 'test-project',
|
|
265
|
-
taskName: 'test-task',
|
|
266
|
-
logItem: JSON.stringify(expectedLogItem)
|
|
267
|
-
}, expect.any(Object));
|
|
238
|
+
const callArgs = mockedAxios.post.mock.calls[0];
|
|
239
|
+
const requestBody = callArgs[1];
|
|
240
|
+
const parsedLogItem = JSON.parse(requestBody.logItem);
|
|
241
|
+
expect(parsedLogItem.metadata).toEqual({
|
|
242
|
+
environment: 'production', // from base
|
|
243
|
+
version: '1.2.0', // from sendLog (highest priority)
|
|
244
|
+
priority: 'sendLog', // from sendLog (highest priority)
|
|
245
|
+
sessionId: 'session-123', // from logItem
|
|
246
|
+
requestId: 'req-456' // from sendLog
|
|
247
|
+
});
|
|
268
248
|
});
|
|
269
249
|
it('should handle all three metadata sources with complex merging', async () => {
|
|
270
250
|
mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
|
|
@@ -275,6 +255,7 @@ describe('HiveLogClient Metadata', () => {
|
|
|
275
255
|
datacenter: 'us-west-2'
|
|
276
256
|
};
|
|
277
257
|
const client = new index_1.HiveLogClient({ ...testConfig, metadata: baseMetadata });
|
|
258
|
+
jest.clearAllMocks();
|
|
278
259
|
const logItem = {
|
|
279
260
|
input: { query: 'search' },
|
|
280
261
|
output: { results: [] },
|
|
@@ -290,28 +271,19 @@ describe('HiveLogClient Metadata', () => {
|
|
|
290
271
|
version: '1.2.0' // overrides both base and logItem
|
|
291
272
|
};
|
|
292
273
|
await client.sendLog({ ...logItem, taskName: 'search-task', type: 'success', boundaries: {}, metadata: logItem.metadata || {} }, sendLogMetadata);
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
taskName: 'search-task',
|
|
307
|
-
type: 'success',
|
|
308
|
-
boundaries: {}
|
|
309
|
-
};
|
|
310
|
-
expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
|
|
311
|
-
projectName: 'test-project',
|
|
312
|
-
taskName: 'search-task',
|
|
313
|
-
logItem: JSON.stringify(expectedLogItem)
|
|
314
|
-
}, expect.any(Object));
|
|
274
|
+
const callArgs = mockedAxios.post.mock.calls[0];
|
|
275
|
+
const requestBody = callArgs[1];
|
|
276
|
+
const parsedLogItem = JSON.parse(requestBody.logItem);
|
|
277
|
+
expect(parsedLogItem.metadata).toEqual({
|
|
278
|
+
environment: 'production', // from base
|
|
279
|
+
service: 'api-gateway', // from base
|
|
280
|
+
version: '1.2.0', // from sendLog (highest priority)
|
|
281
|
+
datacenter: 'us-west-2', // from base
|
|
282
|
+
algorithm: 'fuzzy-search', // from logItem
|
|
283
|
+
processingTime: '250', // from logItem
|
|
284
|
+
requestId: 'req-789', // from sendLog
|
|
285
|
+
userId: 'user-123' // from sendLog
|
|
286
|
+
});
|
|
315
287
|
});
|
|
316
288
|
});
|
|
317
289
|
describe('Edge cases and error handling', () => {
|
|
@@ -319,67 +291,46 @@ describe('HiveLogClient Metadata', () => {
|
|
|
319
291
|
mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
|
|
320
292
|
const baseMetadata = { environment: 'test' };
|
|
321
293
|
const client = new index_1.HiveLogClient({ ...testConfig, metadata: baseMetadata });
|
|
294
|
+
jest.clearAllMocks();
|
|
322
295
|
const logItem = {
|
|
323
296
|
input: 'test'
|
|
324
297
|
// No metadata property
|
|
325
298
|
};
|
|
326
299
|
await client.sendLog({ ...logItem, taskName: 'test-task', type: 'success', boundaries: {}, metadata: {} });
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
environment: 'test' // Only base metadata should be used
|
|
334
|
-
}
|
|
335
|
-
};
|
|
336
|
-
expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
|
|
337
|
-
projectName: 'test-project',
|
|
338
|
-
taskName: 'test-task',
|
|
339
|
-
logItem: JSON.stringify(expectedLogItem)
|
|
340
|
-
}, expect.any(Object));
|
|
300
|
+
const callArgs = mockedAxios.post.mock.calls[0];
|
|
301
|
+
const requestBody = callArgs[1];
|
|
302
|
+
const parsedLogItem = JSON.parse(requestBody.logItem);
|
|
303
|
+
expect(parsedLogItem.metadata).toEqual({
|
|
304
|
+
environment: 'test' // Only base metadata should be used
|
|
305
|
+
});
|
|
341
306
|
});
|
|
342
307
|
it('should handle logItem with undefined metadata', async () => {
|
|
343
308
|
mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
|
|
344
309
|
const baseMetadata = { environment: 'test' };
|
|
345
310
|
const client = new index_1.HiveLogClient({ ...testConfig, metadata: baseMetadata });
|
|
311
|
+
jest.clearAllMocks();
|
|
346
312
|
const logItem = {
|
|
347
313
|
input: 'test',
|
|
348
314
|
metadata: undefined
|
|
349
315
|
};
|
|
350
316
|
await client.sendLog({ ...logItem, taskName: 'test-task', type: 'success', boundaries: {}, metadata: logItem.metadata || {} });
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
type: 'success',
|
|
358
|
-
boundaries: {}
|
|
359
|
-
};
|
|
360
|
-
expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
|
|
361
|
-
projectName: 'test-project',
|
|
362
|
-
taskName: 'test-task',
|
|
363
|
-
logItem: JSON.stringify(expectedLogItem)
|
|
364
|
-
}, expect.any(Object));
|
|
317
|
+
const callArgs = mockedAxios.post.mock.calls[0];
|
|
318
|
+
const requestBody = callArgs[1];
|
|
319
|
+
const parsedLogItem = JSON.parse(requestBody.logItem);
|
|
320
|
+
expect(parsedLogItem.metadata).toEqual({
|
|
321
|
+
environment: 'test' // Only base metadata should be used
|
|
322
|
+
});
|
|
365
323
|
});
|
|
366
324
|
it('should handle empty metadata objects', async () => {
|
|
367
325
|
mockedAxios.post.mockResolvedValueOnce({ data: { success: true } });
|
|
368
326
|
const client = new index_1.HiveLogClient({ ...testConfig, metadata: {} });
|
|
327
|
+
jest.clearAllMocks();
|
|
369
328
|
const logItem = { input: 'test', metadata: {} };
|
|
370
329
|
await client.sendLog({ ...logItem, taskName: 'test-task', type: 'success', boundaries: {}, metadata: logItem.metadata || {} }, {});
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
type: 'success',
|
|
376
|
-
boundaries: {}
|
|
377
|
-
};
|
|
378
|
-
expect(mockedAxios.post).toHaveBeenCalledWith('https://test-host.com/api/tasks/log-ingest', {
|
|
379
|
-
projectName: 'test-project',
|
|
380
|
-
taskName: 'test-task',
|
|
381
|
-
logItem: JSON.stringify(expectedLogItem)
|
|
382
|
-
}, expect.any(Object));
|
|
330
|
+
const callArgs = mockedAxios.post.mock.calls[0];
|
|
331
|
+
const requestBody = callArgs[1];
|
|
332
|
+
const parsedLogItem = JSON.parse(requestBody.logItem);
|
|
333
|
+
expect(parsedLogItem.metadata).toEqual({}); // All empty metadata objects result in empty final metadata
|
|
383
334
|
});
|
|
384
335
|
it('should work in silent mode with metadata', async () => {
|
|
385
336
|
const baseMetadata = { environment: 'test' };
|
|
@@ -392,6 +343,7 @@ describe('HiveLogClient Metadata', () => {
|
|
|
392
343
|
mockedAxios.post.mockRejectedValueOnce(new Error('Network error'));
|
|
393
344
|
const baseMetadata = { environment: 'test' };
|
|
394
345
|
const client = new index_1.HiveLogClient({ ...testConfig, metadata: baseMetadata });
|
|
346
|
+
jest.clearAllMocks();
|
|
395
347
|
const result = await client.sendLog({ input: 'test', taskName: 'test-task', type: 'success', boundaries: {}, metadata: {} }, { requestId: 'req-123' });
|
|
396
348
|
expect(result).toBe('error');
|
|
397
349
|
});
|