@liquidmetal-ai/raindrop 0.5.0 → 0.5.1
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 +113 -53
- package/dist/commands/logs/query.d.ts +30 -0
- package/dist/commands/logs/query.d.ts.map +1 -0
- package/dist/commands/logs/query.js +229 -0
- package/dist/commands/logs/tail.d.ts +22 -0
- package/dist/commands/logs/tail.d.ts.map +1 -0
- package/dist/commands/logs/tail.js +144 -0
- package/dist/commands/tail.d.ts +1 -6
- package/dist/commands/tail.d.ts.map +1 -1
- package/dist/commands/tail.js +9 -203
- package/dist/log-helpers.d.ts +9 -0
- package/dist/log-helpers.d.ts.map +1 -0
- package/dist/log-helpers.js +205 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/oclif.manifest.json +1710 -1294
- package/package.json +3 -3
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { timestampMs } from '@bufbuild/protobuf/wkt';
|
|
2
|
+
export function formatLogAttribute(key, value, displayValue) {
|
|
3
|
+
// Format common attributes nicely
|
|
4
|
+
if (key === 'http.status') {
|
|
5
|
+
const statusCode = parseInt(value);
|
|
6
|
+
const statusEmoji = statusCode >= 200 && statusCode < 300 ? '✅' : statusCode >= 400 ? '❌' : '⚠️';
|
|
7
|
+
return `${key}: ${statusEmoji} ${value}`;
|
|
8
|
+
}
|
|
9
|
+
else if (key === 'http.method' || key === 'http.url') {
|
|
10
|
+
return `${key}: ${value}`;
|
|
11
|
+
}
|
|
12
|
+
else if (key === 'query') {
|
|
13
|
+
// SQL query formatting
|
|
14
|
+
return `🗄️ SQL Query: ${value}`;
|
|
15
|
+
}
|
|
16
|
+
else if (key === 'rows_read') {
|
|
17
|
+
return `📊 Rows Read: ${value}`;
|
|
18
|
+
}
|
|
19
|
+
else if (key === 'rows_written') {
|
|
20
|
+
return `✍️ Rows Written: ${value}`;
|
|
21
|
+
}
|
|
22
|
+
else if (key === 'db') {
|
|
23
|
+
return `🏦 Database: ${value}`;
|
|
24
|
+
}
|
|
25
|
+
else if (key === 'error') {
|
|
26
|
+
if (value && value !== 'undefined') {
|
|
27
|
+
return `❌ Error: ${value}`;
|
|
28
|
+
}
|
|
29
|
+
return null; // Don't display undefined errors
|
|
30
|
+
}
|
|
31
|
+
else if (key === 'fields' || key === 'meta') {
|
|
32
|
+
// Special handling for structured data - show key metrics inline
|
|
33
|
+
try {
|
|
34
|
+
const parsed = JSON.parse(displayValue);
|
|
35
|
+
if (key === 'meta' && parsed) {
|
|
36
|
+
// Extract key database metrics
|
|
37
|
+
const metrics = [];
|
|
38
|
+
if (parsed.duration)
|
|
39
|
+
metrics.push(`${parsed.duration}ms`);
|
|
40
|
+
if (parsed.rows_read)
|
|
41
|
+
metrics.push(`${parsed.rows_read} rows read`);
|
|
42
|
+
if (parsed.rows_written && parsed.rows_written > 0)
|
|
43
|
+
metrics.push(`${parsed.rows_written} rows written`);
|
|
44
|
+
if (parsed.served_by_region)
|
|
45
|
+
metrics.push(`${parsed.served_by_region}`);
|
|
46
|
+
if (parsed.size_after)
|
|
47
|
+
metrics.push(`DB: ${(parsed.size_after / 1024).toFixed(1)}KB`);
|
|
48
|
+
if (metrics.length > 0) {
|
|
49
|
+
return `📊 ${key}: ${metrics.join(', ')}`;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
return `${key}: ${JSON.stringify(parsed, (_, v) => typeof v === 'bigint' ? v.toString() : v)}`;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// For fields or other structured data, show condensed
|
|
57
|
+
return `${key}: ${JSON.stringify(parsed, (_, v) => typeof v === 'bigint' ? v.toString() : v)}`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return `${key}: ${displayValue}`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
return `${key}: ${displayValue}`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function displayEventAttributes(event, logger, indentLevel = ' ') {
|
|
69
|
+
// Show attributes with better formatting
|
|
70
|
+
if (event.attributes && Object.keys(event.attributes).length > 0) {
|
|
71
|
+
Object.entries(event.attributes).forEach(([key, value]) => {
|
|
72
|
+
if (value !== undefined && value !== null) {
|
|
73
|
+
// Parse JSON strings and format objects properly
|
|
74
|
+
let displayValue = value;
|
|
75
|
+
try {
|
|
76
|
+
const parsed = JSON.parse(value);
|
|
77
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
78
|
+
displayValue = JSON.stringify(parsed, (_, v) => {
|
|
79
|
+
if (typeof v === 'bigint') {
|
|
80
|
+
return v.toString();
|
|
81
|
+
}
|
|
82
|
+
return v;
|
|
83
|
+
}, 2);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Not JSON, use as is
|
|
88
|
+
}
|
|
89
|
+
const formattedAttribute = formatLogAttribute(key, value, displayValue);
|
|
90
|
+
if (formattedAttribute) {
|
|
91
|
+
logger.log(`${indentLevel}${formattedAttribute}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export function displayTraceGroupedEvents(events, logger) {
|
|
98
|
+
// Group events by trace ID
|
|
99
|
+
const eventsByTrace = new Map();
|
|
100
|
+
events.forEach((event) => {
|
|
101
|
+
const traceId = event.trace?.eventId || 'unknown';
|
|
102
|
+
if (!eventsByTrace.has(traceId)) {
|
|
103
|
+
eventsByTrace.set(traceId, []);
|
|
104
|
+
}
|
|
105
|
+
const traceEvents = eventsByTrace.get(traceId);
|
|
106
|
+
if (traceEvents) {
|
|
107
|
+
traceEvents.push(event);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
// Display each trace group
|
|
111
|
+
for (const [traceId, traceEvents] of eventsByTrace) {
|
|
112
|
+
if (traceEvents.length === 0)
|
|
113
|
+
continue;
|
|
114
|
+
// Sort events by event order (execution sequence) within trace
|
|
115
|
+
// If eventOrder is not available, fall back to start time
|
|
116
|
+
traceEvents.sort((a, b) => {
|
|
117
|
+
// First try to sort by eventOrder if available
|
|
118
|
+
if (a.eventOrder !== undefined && b.eventOrder !== undefined) {
|
|
119
|
+
return a.eventOrder - b.eventOrder;
|
|
120
|
+
}
|
|
121
|
+
// Fall back to start time if eventOrder is not available
|
|
122
|
+
const aTime = a.trace?.startTime ? timestampMs(a.trace.startTime) : 0;
|
|
123
|
+
const bTime = b.trace?.startTime ? timestampMs(b.trace.startTime) : 0;
|
|
124
|
+
return aTime - bTime;
|
|
125
|
+
});
|
|
126
|
+
const firstEvent = traceEvents[0];
|
|
127
|
+
const lastEvent = traceEvents[traceEvents.length - 1];
|
|
128
|
+
// Calculate trace duration
|
|
129
|
+
const startTime = firstEvent.trace?.startTime ? timestampMs(firstEvent.trace.startTime) : 0;
|
|
130
|
+
const endTime = lastEvent.trace?.endTime ? timestampMs(lastEvent.trace.endTime) :
|
|
131
|
+
(lastEvent.trace?.startTime ? timestampMs(lastEvent.trace.startTime) : 0);
|
|
132
|
+
const traceDuration = endTime > startTime ? ` (${endTime - startTime}ms total)` : '';
|
|
133
|
+
const timestamp = firstEvent.trace?.startTime
|
|
134
|
+
? new Date(timestampMs(firstEvent.trace.startTime)).toLocaleString()
|
|
135
|
+
: 'Unknown time';
|
|
136
|
+
// Show trace header
|
|
137
|
+
logger.log(`[${timestamp}] 🔗 Trace: ${traceId}${traceDuration}`);
|
|
138
|
+
// Show context info once per trace
|
|
139
|
+
if (firstEvent.organization?.id || firstEvent.application?.name) {
|
|
140
|
+
const contextParts = [];
|
|
141
|
+
if (firstEvent.organization?.id)
|
|
142
|
+
contextParts.push(`Org: ${firstEvent.organization.id}`);
|
|
143
|
+
if (firstEvent.application?.name)
|
|
144
|
+
contextParts.push(`App: ${firstEvent.application.name}`);
|
|
145
|
+
if (firstEvent.application?.version?.id)
|
|
146
|
+
contextParts.push(`v${firstEvent.application.version.id}`);
|
|
147
|
+
if (firstEvent.script?.name)
|
|
148
|
+
contextParts.push(`Script: ${firstEvent.script.name}`);
|
|
149
|
+
logger.log(` ${contextParts.join(', ')}`);
|
|
150
|
+
}
|
|
151
|
+
// Display each event in the trace
|
|
152
|
+
traceEvents.forEach((event, index) => {
|
|
153
|
+
const eventName = event.name || 'Event';
|
|
154
|
+
const status = event.status || 'ok';
|
|
155
|
+
const statusEmoji = status === 'error' ? '❌' : '✅';
|
|
156
|
+
// Calculate individual event duration
|
|
157
|
+
let duration = '';
|
|
158
|
+
if (event.trace?.endTime && event.trace?.startTime) {
|
|
159
|
+
const durationMs = timestampMs(event.trace.endTime) - timestampMs(event.trace.startTime);
|
|
160
|
+
duration = ` (${durationMs}ms)`;
|
|
161
|
+
}
|
|
162
|
+
logger.log(` ${index + 1}. ${statusEmoji} ${eventName}${duration}`);
|
|
163
|
+
// Show attributes with proper indentation for grouped events
|
|
164
|
+
displayEventAttributes(event, logger, ' ');
|
|
165
|
+
});
|
|
166
|
+
logger.log(''); // Empty line between traces
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
export function displayIndividualEvents(events, logger) {
|
|
170
|
+
events.forEach((event) => {
|
|
171
|
+
// Format timestamp from trace info
|
|
172
|
+
const timestamp = event.trace?.startTime
|
|
173
|
+
? new Date(timestampMs(event.trace.startTime)).toLocaleString()
|
|
174
|
+
: 'Unknown time';
|
|
175
|
+
const eventName = event.name || 'Event';
|
|
176
|
+
const traceId = event.trace?.eventId || 'N/A';
|
|
177
|
+
const status = event.status || 'ok';
|
|
178
|
+
// Calculate duration if end time is available
|
|
179
|
+
let duration = '';
|
|
180
|
+
if (event.trace?.endTime && event.trace?.startTime) {
|
|
181
|
+
const durationMs = timestampMs(event.trace.endTime) - timestampMs(event.trace.startTime);
|
|
182
|
+
duration = ` (${durationMs}ms)`;
|
|
183
|
+
}
|
|
184
|
+
// Format status with emoji
|
|
185
|
+
const statusEmoji = status === 'error' ? '❌' : '✅';
|
|
186
|
+
logger.log(`[${timestamp}] ${statusEmoji} ${eventName}${duration}`);
|
|
187
|
+
logger.log(` Trace: ${traceId}`);
|
|
188
|
+
// Show attributes with proper indentation for individual events
|
|
189
|
+
displayEventAttributes(event, logger, ' ');
|
|
190
|
+
// Show organization/application context if present
|
|
191
|
+
if (event.organization?.id) {
|
|
192
|
+
logger.log(` Organization: ${event.organization.id}`);
|
|
193
|
+
}
|
|
194
|
+
if (event.application?.name) {
|
|
195
|
+
logger.log(` Application: ${event.application.name}`);
|
|
196
|
+
if (event.application.version?.id) {
|
|
197
|
+
logger.log(` Version: ${event.application.version.id}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (event.script?.name) {
|
|
201
|
+
logger.log(` Script: ${event.script.name}`);
|
|
202
|
+
}
|
|
203
|
+
logger.log(''); // Empty line for readability
|
|
204
|
+
});
|
|
205
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/base-command.ts","../src/build.test.ts","../src/build.ts","../src/codegen.test.ts","../src/codegen.ts","../src/config.test.ts","../src/config.ts","../src/deploy.ts","../src/index.test.ts","../src/index.ts","../src/status.ts","../src/strict-client.ts","../src/trace.ts","../src/commands/tail.ts","../src/commands/annotation/get.ts","../src/commands/annotation/list.ts","../src/commands/annotation/put.ts","../src/commands/auth/list.ts","../src/commands/auth/login.ts","../src/commands/auth/logout.ts","../src/commands/auth/select.ts","../src/commands/bucket/create-credential.ts","../src/commands/bucket/delete-credential.ts","../src/commands/bucket/get-credential.ts","../src/commands/bucket/list-credentials.ts","../src/commands/build/branch.ts","../src/commands/build/checkout.ts","../src/commands/build/clone.ts","../src/commands/build/delete.ts","../src/commands/build/deploy.ts","../src/commands/build/find.ts","../src/commands/build/generate.ts","../src/commands/build/init.ts","../src/commands/build/list.ts","../src/commands/build/sandbox.ts","../src/commands/build/start.ts","../src/commands/build/status.ts","../src/commands/build/stop.ts","../src/commands/build/unsandbox.ts","../src/commands/build/upload.ts","../src/commands/build/validate.ts","../src/commands/build/env/get.ts","../src/commands/build/env/set.ts","../src/commands/build/tools/check.ts","../src/commands/build/tools/fmt.ts","../src/commands/object/delete.ts","../src/commands/object/get.ts","../src/commands/object/list.ts","../src/commands/object/put.ts","../src/commands/query/chunk-search.ts","../src/commands/query/document.ts","../src/commands/query/events.ts","../src/commands/query/search.ts"],"version":"5.8.3"}
|
|
1
|
+
{"root":["../src/base-command.ts","../src/build.test.ts","../src/build.ts","../src/codegen.test.ts","../src/codegen.ts","../src/config.test.ts","../src/config.ts","../src/deploy.ts","../src/index.test.ts","../src/index.ts","../src/log-helpers.ts","../src/status.ts","../src/strict-client.ts","../src/trace.ts","../src/commands/tail.ts","../src/commands/annotation/get.ts","../src/commands/annotation/list.ts","../src/commands/annotation/put.ts","../src/commands/auth/list.ts","../src/commands/auth/login.ts","../src/commands/auth/logout.ts","../src/commands/auth/select.ts","../src/commands/bucket/create-credential.ts","../src/commands/bucket/delete-credential.ts","../src/commands/bucket/get-credential.ts","../src/commands/bucket/list-credentials.ts","../src/commands/build/branch.ts","../src/commands/build/checkout.ts","../src/commands/build/clone.ts","../src/commands/build/delete.ts","../src/commands/build/deploy.ts","../src/commands/build/find.ts","../src/commands/build/generate.ts","../src/commands/build/init.ts","../src/commands/build/list.ts","../src/commands/build/sandbox.ts","../src/commands/build/start.ts","../src/commands/build/status.ts","../src/commands/build/stop.ts","../src/commands/build/unsandbox.ts","../src/commands/build/upload.ts","../src/commands/build/validate.ts","../src/commands/build/env/get.ts","../src/commands/build/env/set.ts","../src/commands/build/tools/check.ts","../src/commands/build/tools/fmt.ts","../src/commands/logs/query.ts","../src/commands/logs/tail.ts","../src/commands/object/delete.ts","../src/commands/object/get.ts","../src/commands/object/list.ts","../src/commands/object/put.ts","../src/commands/query/chunk-search.ts","../src/commands/query/document.ts","../src/commands/query/events.ts","../src/commands/query/search.ts"],"version":"5.8.3"}
|