Openstatus sdk www.openstatus.dev
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: expose HTTP response log methods on MonitorService (#14)

Re-export new types and enums (HTTPResponseLogTiming, HTTPResponseLogListItem,
HTTPResponseLogDetail, HTTPResponseLogPagination, ListMonitorHTTPResponseLogs
request/response, GetMonitorHTTPResponseLog request/response,
HTTPResponseLogRequestStatus, HTTPResponseLogTrigger) and document the new
listMonitorHTTPResponseLogs and getMonitorHTTPResponseLog methods in README and
docs/monitor-service.md.

authored by

Thibault Le Ouay and committed by
GitHub
67b51db5 6e20c613

+709 -6
+61
README.md
··· 365 365 console.log(`P99 latency: ${summary.p99}ms`); 366 366 ``` 367 367 368 + #### `listMonitorHTTPResponseLogs(request)` 369 + 370 + List HTTP response logs for a monitor within the 14-day retention window. 371 + Supports time range filtering and offset pagination. 372 + 373 + ```typescript 374 + const { logs, pagination } = await client.monitor.v1.MonitorService 375 + .listMonitorHTTPResponseLogs({ 376 + id: "mon_123", 377 + fromTimestamp: BigInt(Date.now() - 24 * 60 * 60 * 1000), // last 24h 378 + toTimestamp: BigInt(Date.now()), 379 + limit: 25, 380 + offset: 0, 381 + }); 382 + 383 + for (const log of logs) { 384 + console.log(`${log.timestamp}: ${log.statusCode} (${log.latency}ms)`); 385 + } 386 + 387 + if (pagination?.hasMore) { 388 + console.log(`Next offset: ${pagination.nextOffset}`); 389 + } 390 + ``` 391 + 392 + #### `getMonitorHTTPResponseLog(request)` 393 + 394 + Get a single HTTP response log with full debugging details (URL, headers, 395 + assertions, error message). 396 + 397 + ```typescript 398 + const { log } = await client.monitor.v1.MonitorService 399 + .getMonitorHTTPResponseLog({ 400 + id: "mon_123", 401 + logId: "log_456", 402 + }); 403 + 404 + console.log(`URL: ${log?.url}`); 405 + console.log(`Errored: ${log?.error}`); 406 + console.log(`Message: ${log?.message ?? "n/a"}`); 407 + console.log(`Status code: ${log?.log?.statusCode}`); 408 + 409 + for (const [key, value] of Object.entries(log?.headers ?? {})) { 410 + console.log(` ${key}: ${value}`); 411 + } 412 + ``` 413 + 368 414 --- 369 415 370 416 ### Health Service ··· 1367 1413 | `TIME_RANGE_1D` | Last 1 day | 1368 1414 | `TIME_RANGE_7D` | Last 7 days | 1369 1415 | `TIME_RANGE_14D` | Last 14 days | 1416 + 1417 + #### HTTPResponseLogRequestStatus 1418 + 1419 + | Value | Description | 1420 + | ------------------------------------------- | ---------------------------------- | 1421 + | `HTTP_RESPONSE_LOG_REQUEST_STATUS_SUCCESS` | Response satisfied assertions | 1422 + | `HTTP_RESPONSE_LOG_REQUEST_STATUS_ERROR` | Response failed its assertions | 1423 + | `HTTP_RESPONSE_LOG_REQUEST_STATUS_DEGRADED` | Response slower than the threshold | 1424 + 1425 + #### HTTPResponseLogTrigger 1426 + 1427 + | Value | Description | 1428 + | -------------------------------- | ------------------------- | 1429 + | `HTTP_RESPONSE_LOG_TRIGGER_CRON` | Scheduled monitor run | 1430 + | `HTTP_RESPONSE_LOG_TRIGGER_API` | API-triggered monitor run | 1370 1431 1371 1432 #### StatusReportStatus 1372 1433
+85 -3
docs/monitor-service.md
··· 2 2 3 3 # Monitor Service 4 4 5 - Manage HTTP, TCP, and DNS monitors. The Monitor Service provides 12 RPC methods 6 - for creating, updating, listing, triggering, deleting, and querying monitor 7 - status and metrics. 5 + Manage HTTP, TCP, and DNS monitors. The Monitor Service provides 14 RPC methods 6 + for creating, updating, listing, triggering, deleting, querying monitor status 7 + and metrics, and inspecting HTTP response logs. 8 8 9 9 All examples assume you have created a client: 10 10 ··· 357 357 (`totalSuccessful`, `totalDegraded`, `totalFailed`) are `bigint` values. The 358 358 `regions` parameter is optional — pass an empty array to get metrics across all 359 359 regions. 360 + 361 + ## List Monitor HTTP Response Logs 362 + 363 + List HTTP response logs for a monitor within the 14-day retention window. 364 + Supports time-window filtering and offset-based pagination. 365 + 366 + ```typescript 367 + import { 368 + createOpenStatusClient, 369 + HTTPResponseLogRequestStatus, 370 + HTTPResponseLogTrigger, 371 + Region, 372 + } from "@openstatus/sdk-node"; 373 + 374 + const client = createOpenStatusClient({ 375 + apiKey: process.env.OPENSTATUS_API_KEY, 376 + }); 377 + 378 + const { logs, pagination } = await client.monitor.v1.MonitorService 379 + .listMonitorHTTPResponseLogs({ 380 + id: "mon_123", 381 + fromTimestamp: BigInt(Date.now() - 24 * 60 * 60 * 1000), 382 + toTimestamp: BigInt(Date.now()), 383 + limit: 25, 384 + offset: 0, 385 + }); 386 + 387 + for (const log of logs) { 388 + console.log( 389 + `[${Region[log.region]}] ${log.timestamp}: ` + 390 + `${log.statusCode ?? "n/a"} (${log.latency}ms) ` + 391 + `status=${HTTPResponseLogRequestStatus[log.requestStatus]} ` + 392 + `trigger=${HTTPResponseLogTrigger[log.trigger]}`, 393 + ); 394 + } 395 + 396 + if (pagination?.hasMore) { 397 + console.log(`Next offset: ${pagination.nextOffset}`); 398 + } 399 + ``` 400 + 401 + Request parameters: 402 + 403 + | Parameter | Type | Description | 404 + | --------------- | ----------------- | ----------------------------------------------- | 405 + | `id` | string | Monitor ID (required) | 406 + | `fromTimestamp` | bigint (optional) | Window start, Unix milliseconds (14d retention) | 407 + | `toTimestamp` | bigint (optional) | Window end, Unix milliseconds | 408 + | `limit` | number (optional) | Max results to return (1–100, default 25) | 409 + | `offset` | number (optional) | Number of results to skip (default 0) | 410 + 411 + Each `HTTPResponseLogListItem` includes `id`, `latency`, `statusCode`, 412 + `monitorId`, `requestStatus`, `region`, `cronTimestamp`, `trigger`, `timestamp`, 413 + and an optional `timing` breakdown (`dns`, `connect`, `tls`, `ttfb`, 414 + `transfer`). 415 + 416 + ## Get Monitor HTTP Response Log 417 + 418 + Get full debugging details for a single response log: the requested URL, 419 + redacted response headers, error message, and serialized assertions. 420 + 421 + ```typescript 422 + const { log } = await client.monitor.v1.MonitorService 423 + .getMonitorHTTPResponseLog({ 424 + id: "mon_123", 425 + logId: "log_456", 426 + }); 427 + 428 + console.log(`URL: ${log?.url}`); 429 + console.log(`Errored: ${log?.error}`); 430 + console.log(`Message: ${log?.message ?? "n/a"}`); 431 + console.log(`Status code: ${log?.log?.statusCode}`); 432 + console.log(`Assertions: ${log?.assertions ?? "n/a"}`); 433 + 434 + for (const [key, value] of Object.entries(log?.headers ?? {})) { 435 + console.log(` ${key}: ${value}`); 436 + } 437 + ``` 438 + 439 + The `log.log` field embeds the same `HTTPResponseLogListItem` returned by 440 + `listMonitorHTTPResponseLogs`, so timing and classification fields are available 441 + alongside the detail fields.
+59 -1
example.ts
··· 3 3 * 4 4 * Run with: deno task dev 5 5 */ 6 - import { type HTTPMonitor, openstatus } from "./src/mod.ts"; 6 + import { 7 + type HTTPMonitor, 8 + HTTPResponseLogRequestStatus, 9 + HTTPResponseLogTrigger, 10 + openstatus, 11 + Region, 12 + } from "./src/mod.ts"; 7 13 8 14 async function main(): Promise<void> { 9 15 console.log("OpenStatus SDK Example\n"); ··· 44 50 })`, 45 51 ); 46 52 }); 53 + } 54 + 55 + console.log("4. Listing HTTP response logs for monitor..."); 56 + const { logs, pagination } = await openstatus.monitor.v1.MonitorService 57 + .listMonitorHTTPResponseLogs({ id: "ID", limit: 10 }, { headers }); 58 + 59 + console.log(` Found ${logs.length} logs (hasMore=${pagination?.hasMore})`); 60 + for (const log of logs) { 61 + const ts = new Date(Number(log.timestamp)).toISOString(); 62 + const status = log.statusCode ?? "—"; 63 + const region = Region[log.region] ?? log.region; 64 + const requestStatus = HTTPResponseLogRequestStatus[log.requestStatus] ?? 65 + log.requestStatus; 66 + const trigger = HTTPResponseLogTrigger[log.trigger] ?? log.trigger; 67 + console.log( 68 + ` ${ts} ${status} ${log.latency}ms ${region} ` + 69 + `${requestStatus} ${trigger} id=${log.id ?? "—"}`, 70 + ); 71 + if (log.timing) { 72 + console.log( 73 + ` timing: dns=${log.timing.dns}ms connect=${log.timing.connect}ms ` + 74 + `tls=${log.timing.tls}ms ttfb=${log.timing.ttfb}ms ` + 75 + `transfer=${log.timing.transfer}ms`, 76 + ); 77 + } 78 + } 79 + 80 + // 5. Fetch full detail for the most recent log 81 + const firstLog = logs[0]; 82 + if (firstLog?.id) { 83 + console.log(`\n5. Getting log detail for ${firstLog.id}...`); 84 + const { log: detail } = await openstatus.monitor.v1.MonitorService 85 + .getMonitorHTTPResponseLog( 86 + { id: "9167", logId: firstLog.id }, 87 + { headers }, 88 + ); 89 + 90 + if (detail) { 91 + console.log(` URL: ${detail.url}`); 92 + console.log(` Errored: ${detail.error}`); 93 + console.log(` Message: ${detail.message ?? "—"}`); 94 + console.log(` Status: ${detail.log?.statusCode ?? "—"}`); 95 + console.log(` Assertions: ${detail.assertions ?? "—"}`); 96 + 97 + const headerEntries = Object.entries(detail.headers); 98 + if (headerEntries.length > 0) { 99 + console.log(` Headers:`); 100 + for (const [key, value] of headerEntries) { 101 + console.log(` ${key}: ${value}`); 102 + } 103 + } 104 + } 47 105 } 48 106 } 49 107
+489 -1
src/gen/openstatus/monitor/v1/service_pb.ts
··· 31 31 */ 32 32 export const file_openstatus_monitor_v1_service: GenFile = /*@__PURE__*/ 33 33 fileDesc( 34 - "CiNvcGVuc3RhdHVzL21vbml0b3IvdjEvc2VydmljZS5wcm90bxIVb3BlbnN0YXR1cy5tb25pdG9yLnYxIlcKGENyZWF0ZUhUVFBNb25pdG9yUmVxdWVzdBI7Cgdtb25pdG9yGAEgASgLMiIub3BlbnN0YXR1cy5tb25pdG9yLnYxLkhUVFBNb25pdG9yQga6SAPIAQEiUAoZQ3JlYXRlSFRUUE1vbml0b3JSZXNwb25zZRIzCgdtb25pdG9yGAEgASgLMiIub3BlbnN0YXR1cy5tb25pdG9yLnYxLkhUVFBNb25pdG9yIlUKF0NyZWF0ZVRDUE1vbml0b3JSZXF1ZXN0EjoKB21vbml0b3IYASABKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuVENQTW9uaXRvckIGukgDyAEBIk4KGENyZWF0ZVRDUE1vbml0b3JSZXNwb25zZRIyCgdtb25pdG9yGAEgASgLMiEub3BlbnN0YXR1cy5tb25pdG9yLnYxLlRDUE1vbml0b3IiVQoXQ3JlYXRlRE5TTW9uaXRvclJlcXVlc3QSOgoHbW9uaXRvchgBIAEoCzIhLm9wZW5zdGF0dXMubW9uaXRvci52MS5ETlNNb25pdG9yQga6SAPIAQEiTgoYQ3JlYXRlRE5TTW9uaXRvclJlc3BvbnNlEjIKB21vbml0b3IYASABKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuRE5TTW9uaXRvciJ1ChhVcGRhdGVIVFRQTW9uaXRvclJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESOAoHbW9uaXRvchgCIAEoCzIiLm9wZW5zdGF0dXMubW9uaXRvci52MS5IVFRQTW9uaXRvckgAiAEBQgoKCF9tb25pdG9yIlAKGVVwZGF0ZUhUVFBNb25pdG9yUmVzcG9uc2USMwoHbW9uaXRvchgBIAEoCzIiLm9wZW5zdGF0dXMubW9uaXRvci52MS5IVFRQTW9uaXRvciJzChdVcGRhdGVUQ1BNb25pdG9yUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARI3Cgdtb25pdG9yGAIgASgLMiEub3BlbnN0YXR1cy5tb25pdG9yLnYxLlRDUE1vbml0b3JIAIgBAUIKCghfbW9uaXRvciJOChhVcGRhdGVUQ1BNb25pdG9yUmVzcG9uc2USMgoHbW9uaXRvchgBIAEoCzIhLm9wZW5zdGF0dXMubW9uaXRvci52MS5UQ1BNb25pdG9yInMKF1VwZGF0ZUROU01vbml0b3JSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEjcKB21vbml0b3IYAiABKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuRE5TTW9uaXRvckgAiAEBQgoKCF9tb25pdG9yIk4KGFVwZGF0ZUROU01vbml0b3JSZXNwb25zZRIyCgdtb25pdG9yGAEgASgLMiEub3BlbnN0YXR1cy5tb25pdG9yLnYxLkROU01vbml0b3IiLAoVVHJpZ2dlck1vbml0b3JSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABIikKFlRyaWdnZXJNb25pdG9yUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCCIrChREZWxldGVNb25pdG9yUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQASIoChVEZWxldGVNb25pdG9yUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCCJnChNMaXN0TW9uaXRvcnNSZXF1ZXN0Eh0KBWxpbWl0GAEgASgFQgm6SAYaBBhkKAFIAIgBARIcCgZvZmZzZXQYAiABKAVCB7pIBBoCKABIAYgBAUIICgZfbGltaXRCCQoHX29mZnNldCLXAQoUTGlzdE1vbml0b3JzUmVzcG9uc2USOQoNaHR0cF9tb25pdG9ycxgBIAMoCzIiLm9wZW5zdGF0dXMubW9uaXRvci52MS5IVFRQTW9uaXRvchI3Cgx0Y3BfbW9uaXRvcnMYAiADKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuVENQTW9uaXRvchI3CgxkbnNfbW9uaXRvcnMYAyADKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuRE5TTW9uaXRvchISCgp0b3RhbF9zaXplGAQgASgFIi4KF0dldE1vbml0b3JTdGF0dXNSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABInMKDFJlZ2lvblN0YXR1cxItCgZyZWdpb24YASABKA4yHS5vcGVuc3RhdHVzLm1vbml0b3IudjEuUmVnaW9uEjQKBnN0YXR1cxgCIAEoDjIkLm9wZW5zdGF0dXMubW9uaXRvci52MS5Nb25pdG9yU3RhdHVzIlwKGEdldE1vbml0b3JTdGF0dXNSZXNwb25zZRIKCgJpZBgBIAEoCRI0CgdyZWdpb25zGAIgAygLMiMub3BlbnN0YXR1cy5tb25pdG9yLnYxLlJlZ2lvblN0YXR1cyKxAQoNTW9uaXRvckNvbmZpZxIyCgRodHRwGAEgASgLMiIub3BlbnN0YXR1cy5tb25pdG9yLnYxLkhUVFBNb25pdG9ySAASMAoDdGNwGAIgASgLMiEub3BlbnN0YXR1cy5tb25pdG9yLnYxLlRDUE1vbml0b3JIABIwCgNkbnMYAyABKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuRE5TTW9uaXRvckgAQggKBmNvbmZpZyKfAQoYR2V0TW9uaXRvclN1bW1hcnlSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEjQKCnRpbWVfcmFuZ2UYAiABKA4yIC5vcGVuc3RhdHVzLm1vbml0b3IudjEuVGltZVJhbmdlEjgKB3JlZ2lvbnMYAyADKA4yHS5vcGVuc3RhdHVzLm1vbml0b3IudjEuUmVnaW9uQgi6SAWSAQIQHCKsAgoZR2V0TW9uaXRvclN1bW1hcnlSZXNwb25zZRIKCgJpZBgBIAEoCRIUCgxsYXN0X3BpbmdfYXQYAiABKAkSGAoQdG90YWxfc3VjY2Vzc2Z1bBgDIAEoAxIWCg50b3RhbF9kZWdyYWRlZBgEIAEoAxIUCgx0b3RhbF9mYWlsZWQYBSABKAMSCwoDcDUwGAYgASgDEgsKA3A3NRgHIAEoAxILCgNwOTAYCCABKAMSCwoDcDk1GAkgASgDEgsKA3A5ORgKIAEoAxI0Cgp0aW1lX3JhbmdlGAsgASgOMiAub3BlbnN0YXR1cy5tb25pdG9yLnYxLlRpbWVSYW5nZRIuCgdyZWdpb25zGAwgAygOMh0ub3BlbnN0YXR1cy5tb25pdG9yLnYxLlJlZ2lvbiIoChFHZXRNb25pdG9yUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQASJLChJHZXRNb25pdG9yUmVzcG9uc2USNQoHbW9uaXRvchgBIAEoCzIkLm9wZW5zdGF0dXMubW9uaXRvci52MS5Nb25pdG9yQ29uZmlnKmEKCVRpbWVSYW5nZRIaChZUSU1FX1JBTkdFX1VOU1BFQ0lGSUVEEAASEQoNVElNRV9SQU5HRV8xRBABEhEKDVRJTUVfUkFOR0VfN0QQAhISCg5USU1FX1JBTkdFXzE0RBADMukRCg5Nb25pdG9yU2VydmljZRK5AwoRQ3JlYXRlSFRUUE1vbml0b3ISLy5vcGVuc3RhdHVzLm1vbml0b3IudjEuQ3JlYXRlSFRUUE1vbml0b3JSZXF1ZXN0GjAub3BlbnN0YXR1cy5tb25pdG9yLnYxLkNyZWF0ZUhUVFBNb25pdG9yUmVzcG9uc2UiwAK6R7wCGrkCQ3JlYXRlcyBhIG5ldyBIVFRQIG1vbml0b3IgaW4gdGhlIGF1dGhlbnRpY2F0ZWQgd29ya3NwYWNlLiBDb25maWd1cmUgdGhlIHRhcmdldCBVUkwsIEhUVFAgbWV0aG9kLCByZXF1ZXN0IGhlYWRlcnMgYW5kIGJvZHksIHJlc3BvbnNlIGFzc2VydGlvbnMgKHN0YXR1cyBjb2RlLCBib2R5IGNvbnRlbnQsIGhlYWRlcnMpLCBjaGVjayBwZXJpb2RpY2l0eSwgZ2VvZ3JhcGhpYyByZWdpb25zLCBhbmQgb3B0aW9uYWwgT3BlblRlbGVtZXRyeSBleHBvcnQuIFRoZSBtb25pdG9yIHN0YXJ0cyBjaGVja2luZyBpbW1lZGlhdGVseSBpZiBzZXQgdG8gYWN0aXZlLhJzChBDcmVhdGVUQ1BNb25pdG9yEi4ub3BlbnN0YXR1cy5tb25pdG9yLnYxLkNyZWF0ZVRDUE1vbml0b3JSZXF1ZXN0Gi8ub3BlbnN0YXR1cy5tb25pdG9yLnYxLkNyZWF0ZVRDUE1vbml0b3JSZXNwb25zZRJzChBDcmVhdGVETlNNb25pdG9yEi4ub3BlbnN0YXR1cy5tb25pdG9yLnYxLkNyZWF0ZUROU01vbml0b3JSZXF1ZXN0Gi8ub3BlbnN0YXR1cy5tb25pdG9yLnYxLkNyZWF0ZUROU01vbml0b3JSZXNwb25zZRJ2ChFVcGRhdGVIVFRQTW9uaXRvchIvLm9wZW5zdGF0dXMubW9uaXRvci52MS5VcGRhdGVIVFRQTW9uaXRvclJlcXVlc3QaMC5vcGVuc3RhdHVzLm1vbml0b3IudjEuVXBkYXRlSFRUUE1vbml0b3JSZXNwb25zZRJzChBVcGRhdGVUQ1BNb25pdG9yEi4ub3BlbnN0YXR1cy5tb25pdG9yLnYxLlVwZGF0ZVRDUE1vbml0b3JSZXF1ZXN0Gi8ub3BlbnN0YXR1cy5tb25pdG9yLnYxLlVwZGF0ZVRDUE1vbml0b3JSZXNwb25zZRJzChBVcGRhdGVETlNNb25pdG9yEi4ub3BlbnN0YXR1cy5tb25pdG9yLnYxLlVwZGF0ZUROU01vbml0b3JSZXF1ZXN0Gi8ub3BlbnN0YXR1cy5tb25pdG9yLnYxLlVwZGF0ZUROU01vbml0b3JSZXNwb25zZRLpAgoOVHJpZ2dlck1vbml0b3ISLC5vcGVuc3RhdHVzLm1vbml0b3IudjEuVHJpZ2dlck1vbml0b3JSZXF1ZXN0Gi0ub3BlbnN0YXR1cy5tb25pdG9yLnYxLlRyaWdnZXJNb25pdG9yUmVzcG9uc2Ui+QG6R/UBGvIBTWFudWFsbHkgdHJpZ2dlcnMgYW4gaW1tZWRpYXRlIGNoZWNrIGZvciB0aGUgc3BlY2lmaWVkIG1vbml0b3IgYWNyb3NzIGFsbCBjb25maWd1cmVkIHJlZ2lvbnMuIFRoaXMgb3BlcmF0aW9uIGlzIHJhdGUtbGltaXRlZCB1bmRlciB0aGUgc3ludGhldGljLWNoZWNrcyBxdW90YS4gQSBtb25pdG9yIHJ1biByZWNvcmQgaXMgY3JlYXRlZCBhbmQgdGhlIGNoZWNrIGlzIGRpc3BhdGNoZWQgdG8gdGhlIGNoZWNrZXIgc2VydmljZS4SagoNRGVsZXRlTW9uaXRvchIrLm9wZW5zdGF0dXMubW9uaXRvci52MS5EZWxldGVNb25pdG9yUmVxdWVzdBosLm9wZW5zdGF0dXMubW9uaXRvci52MS5EZWxldGVNb25pdG9yUmVzcG9uc2USbAoMTGlzdE1vbml0b3JzEioub3BlbnN0YXR1cy5tb25pdG9yLnYxLkxpc3RNb25pdG9yc1JlcXVlc3QaKy5vcGVuc3RhdHVzLm1vbml0b3IudjEuTGlzdE1vbml0b3JzUmVzcG9uc2UiA5ACARJ4ChBHZXRNb25pdG9yU3RhdHVzEi4ub3BlbnN0YXR1cy5tb25pdG9yLnYxLkdldE1vbml0b3JTdGF0dXNSZXF1ZXN0Gi8ub3BlbnN0YXR1cy5tb25pdG9yLnYxLkdldE1vbml0b3JTdGF0dXNSZXNwb25zZSIDkAIBEqYDChFHZXRNb25pdG9yU3VtbWFyeRIvLm9wZW5zdGF0dXMubW9uaXRvci52MS5HZXRNb25pdG9yU3VtbWFyeVJlcXVlc3QaMC5vcGVuc3RhdHVzLm1vbml0b3IudjEuR2V0TW9uaXRvclN1bW1hcnlSZXNwb25zZSKtApACAbpHpgIaowJSZXR1cm5zIGFnZ3JlZ2F0ZWQgbWV0cmljcyBmb3IgYSBtb25pdG9yIGluY2x1ZGluZyBsYXRlbmN5IHBlcmNlbnRpbGVzIChwNTAsIHA3NSwgcDkwLCBwOTUsIHA5OSksIHJlcXVlc3QgY291bnRzIGJ5IHN0YXR1cyAoc3VjY2Vzc2Z1bCwgZGVncmFkZWQsIGZhaWxlZCksIGFuZCB0aGUgdGltZXN0YW1wIG9mIHRoZSBsYXN0IGNoZWNrLiBNZXRyaWNzIGNhbiBiZSBzY29wZWQgdG8gYSB0aW1lIHJhbmdlICgxIGRheSwgNyBkYXlzLCBvciAxNCBkYXlzKSBhbmQgZmlsdGVyZWQgYnkgc3BlY2lmaWMgcmVnaW9ucy4SZgoKR2V0TW9uaXRvchIoLm9wZW5zdGF0dXMubW9uaXRvci52MS5HZXRNb25pdG9yUmVxdWVzdBopLm9wZW5zdGF0dXMubW9uaXRvci52MS5HZXRNb25pdG9yUmVzcG9uc2UiA5ACAUJTWlFnaXRodWIuY29tL29wZW5zdGF0dXNocS9vcGVuc3RhdHVzL3BhY2thZ2VzL3Byb3RvL29wZW5zdGF0dXMvbW9uaXRvci92MTttb25pdG9ydjFiBnByb3RvMw", 34 + "CiNvcGVuc3RhdHVzL21vbml0b3IvdjEvc2VydmljZS5wcm90bxIVb3BlbnN0YXR1cy5tb25pdG9yLnYxIlcKGENyZWF0ZUhUVFBNb25pdG9yUmVxdWVzdBI7Cgdtb25pdG9yGAEgASgLMiIub3BlbnN0YXR1cy5tb25pdG9yLnYxLkhUVFBNb25pdG9yQga6SAPIAQEiUAoZQ3JlYXRlSFRUUE1vbml0b3JSZXNwb25zZRIzCgdtb25pdG9yGAEgASgLMiIub3BlbnN0YXR1cy5tb25pdG9yLnYxLkhUVFBNb25pdG9yIlUKF0NyZWF0ZVRDUE1vbml0b3JSZXF1ZXN0EjoKB21vbml0b3IYASABKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuVENQTW9uaXRvckIGukgDyAEBIk4KGENyZWF0ZVRDUE1vbml0b3JSZXNwb25zZRIyCgdtb25pdG9yGAEgASgLMiEub3BlbnN0YXR1cy5tb25pdG9yLnYxLlRDUE1vbml0b3IiVQoXQ3JlYXRlRE5TTW9uaXRvclJlcXVlc3QSOgoHbW9uaXRvchgBIAEoCzIhLm9wZW5zdGF0dXMubW9uaXRvci52MS5ETlNNb25pdG9yQga6SAPIAQEiTgoYQ3JlYXRlRE5TTW9uaXRvclJlc3BvbnNlEjIKB21vbml0b3IYASABKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuRE5TTW9uaXRvciJ1ChhVcGRhdGVIVFRQTW9uaXRvclJlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESOAoHbW9uaXRvchgCIAEoCzIiLm9wZW5zdGF0dXMubW9uaXRvci52MS5IVFRQTW9uaXRvckgAiAEBQgoKCF9tb25pdG9yIlAKGVVwZGF0ZUhUVFBNb25pdG9yUmVzcG9uc2USMwoHbW9uaXRvchgBIAEoCzIiLm9wZW5zdGF0dXMubW9uaXRvci52MS5IVFRQTW9uaXRvciJzChdVcGRhdGVUQ1BNb25pdG9yUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARI3Cgdtb25pdG9yGAIgASgLMiEub3BlbnN0YXR1cy5tb25pdG9yLnYxLlRDUE1vbml0b3JIAIgBAUIKCghfbW9uaXRvciJOChhVcGRhdGVUQ1BNb25pdG9yUmVzcG9uc2USMgoHbW9uaXRvchgBIAEoCzIhLm9wZW5zdGF0dXMubW9uaXRvci52MS5UQ1BNb25pdG9yInMKF1VwZGF0ZUROU01vbml0b3JSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEjcKB21vbml0b3IYAiABKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuRE5TTW9uaXRvckgAiAEBQgoKCF9tb25pdG9yIk4KGFVwZGF0ZUROU01vbml0b3JSZXNwb25zZRIyCgdtb25pdG9yGAEgASgLMiEub3BlbnN0YXR1cy5tb25pdG9yLnYxLkROU01vbml0b3IiLAoVVHJpZ2dlck1vbml0b3JSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABIikKFlRyaWdnZXJNb25pdG9yUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCCIrChREZWxldGVNb25pdG9yUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQASIoChVEZWxldGVNb25pdG9yUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCCJnChNMaXN0TW9uaXRvcnNSZXF1ZXN0Eh0KBWxpbWl0GAEgASgFQgm6SAYaBBhkKAFIAIgBARIcCgZvZmZzZXQYAiABKAVCB7pIBBoCKABIAYgBAUIICgZfbGltaXRCCQoHX29mZnNldCLXAQoUTGlzdE1vbml0b3JzUmVzcG9uc2USOQoNaHR0cF9tb25pdG9ycxgBIAMoCzIiLm9wZW5zdGF0dXMubW9uaXRvci52MS5IVFRQTW9uaXRvchI3Cgx0Y3BfbW9uaXRvcnMYAiADKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuVENQTW9uaXRvchI3CgxkbnNfbW9uaXRvcnMYAyADKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuRE5TTW9uaXRvchISCgp0b3RhbF9zaXplGAQgASgFIi4KF0dldE1vbml0b3JTdGF0dXNSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABInMKDFJlZ2lvblN0YXR1cxItCgZyZWdpb24YASABKA4yHS5vcGVuc3RhdHVzLm1vbml0b3IudjEuUmVnaW9uEjQKBnN0YXR1cxgCIAEoDjIkLm9wZW5zdGF0dXMubW9uaXRvci52MS5Nb25pdG9yU3RhdHVzIlwKGEdldE1vbml0b3JTdGF0dXNSZXNwb25zZRIKCgJpZBgBIAEoCRI0CgdyZWdpb25zGAIgAygLMiMub3BlbnN0YXR1cy5tb25pdG9yLnYxLlJlZ2lvblN0YXR1cyKxAQoNTW9uaXRvckNvbmZpZxIyCgRodHRwGAEgASgLMiIub3BlbnN0YXR1cy5tb25pdG9yLnYxLkhUVFBNb25pdG9ySAASMAoDdGNwGAIgASgLMiEub3BlbnN0YXR1cy5tb25pdG9yLnYxLlRDUE1vbml0b3JIABIwCgNkbnMYAyABKAsyIS5vcGVuc3RhdHVzLm1vbml0b3IudjEuRE5TTW9uaXRvckgAQggKBmNvbmZpZyKfAQoYR2V0TW9uaXRvclN1bW1hcnlSZXF1ZXN0EhMKAmlkGAEgASgJQge6SARyAhABEjQKCnRpbWVfcmFuZ2UYAiABKA4yIC5vcGVuc3RhdHVzLm1vbml0b3IudjEuVGltZVJhbmdlEjgKB3JlZ2lvbnMYAyADKA4yHS5vcGVuc3RhdHVzLm1vbml0b3IudjEuUmVnaW9uQgi6SAWSAQIQHCKsAgoZR2V0TW9uaXRvclN1bW1hcnlSZXNwb25zZRIKCgJpZBgBIAEoCRIUCgxsYXN0X3BpbmdfYXQYAiABKAkSGAoQdG90YWxfc3VjY2Vzc2Z1bBgDIAEoAxIWCg50b3RhbF9kZWdyYWRlZBgEIAEoAxIUCgx0b3RhbF9mYWlsZWQYBSABKAMSCwoDcDUwGAYgASgDEgsKA3A3NRgHIAEoAxILCgNwOTAYCCABKAMSCwoDcDk1GAkgASgDEgsKA3A5ORgKIAEoAxI0Cgp0aW1lX3JhbmdlGAsgASgOMiAub3BlbnN0YXR1cy5tb25pdG9yLnYxLlRpbWVSYW5nZRIuCgdyZWdpb25zGAwgAygOMh0ub3BlbnN0YXR1cy5tb25pdG9yLnYxLlJlZ2lvbiIoChFHZXRNb25pdG9yUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQASJLChJHZXRNb25pdG9yUmVzcG9uc2USNQoHbW9uaXRvchgBIAEoCzIkLm9wZW5zdGF0dXMubW9uaXRvci52MS5Nb25pdG9yQ29uZmlnImIKFUhUVFBSZXNwb25zZUxvZ1RpbWluZxILCgNkbnMYASABKAUSDwoHY29ubmVjdBgCIAEoBRILCgN0bHMYAyABKAUSDAoEdHRmYhgEIAEoBRIQCgh0cmFuc2ZlchgFIAEoBSK1AwoXSFRUUFJlc3BvbnNlTG9nTGlzdEl0ZW0SDwoCaWQYASABKAlIAIgBARIPCgdsYXRlbmN5GAIgASgFEhgKC3N0YXR1c19jb2RlGAMgASgFSAGIAQESEgoKbW9uaXRvcl9pZBgEIAEoCRJLCg5yZXF1ZXN0X3N0YXR1cxgFIAEoDjIzLm9wZW5zdGF0dXMubW9uaXRvci52MS5IVFRQUmVzcG9uc2VMb2dSZXF1ZXN0U3RhdHVzEi0KBnJlZ2lvbhgGIAEoDjIdLm9wZW5zdGF0dXMubW9uaXRvci52MS5SZWdpb24SFgoOY3Jvbl90aW1lc3RhbXAYByABKAMSPgoHdHJpZ2dlchgIIAEoDjItLm9wZW5zdGF0dXMubW9uaXRvci52MS5IVFRQUmVzcG9uc2VMb2dUcmlnZ2VyEhEKCXRpbWVzdGFtcBgJIAEoAxJBCgZ0aW1pbmcYCiABKAsyLC5vcGVuc3RhdHVzLm1vbml0b3IudjEuSFRUUFJlc3BvbnNlTG9nVGltaW5nSAKIAQFCBQoDX2lkQg4KDF9zdGF0dXNfY29kZUIJCgdfdGltaW5nIrYCChVIVFRQUmVzcG9uc2VMb2dEZXRhaWwSOwoDbG9nGAEgASgLMi4ub3BlbnN0YXR1cy5tb25pdG9yLnYxLkhUVFBSZXNwb25zZUxvZ0xpc3RJdGVtEgsKA3VybBgCIAEoCRINCgVlcnJvchgDIAEoCBIUCgdtZXNzYWdlGAQgASgJSACIAQESSgoHaGVhZGVycxgFIAMoCzI5Lm9wZW5zdGF0dXMubW9uaXRvci52MS5IVFRQUmVzcG9uc2VMb2dEZXRhaWwuSGVhZGVyc0VudHJ5EhcKCmFzc2VydGlvbnMYBiABKAlIAYgBARouCgxIZWFkZXJzRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4AUIKCghfbWVzc2FnZUINCgtfYXNzZXJ0aW9ucyLnAQoiTGlzdE1vbml0b3JIVFRQUmVzcG9uc2VMb2dzUmVxdWVzdBITCgJpZBgBIAEoCUIHukgEcgIQARIbCg5mcm9tX3RpbWVzdGFtcBgCIAEoA0gAiAEBEhkKDHRvX3RpbWVzdGFtcBgDIAEoA0gBiAEBEh0KBWxpbWl0GAQgASgFQgm6SAYaBBhkKAFIAogBARIcCgZvZmZzZXQYBSABKAVCB7pIBBoCKABIA4gBAUIRCg9fZnJvbV90aW1lc3RhbXBCDwoNX3RvX3RpbWVzdGFtcEIICgZfbGltaXRCCQoHX29mZnNldCJ2ChlIVFRQUmVzcG9uc2VMb2dQYWdpbmF0aW9uEg0KBWxpbWl0GAEgASgFEg4KBm9mZnNldBgCIAEoBRIQCghoYXNfbW9yZRgDIAEoCBIYCgtuZXh0X29mZnNldBgEIAEoBUgAiAEBQg4KDF9uZXh0X29mZnNldCKpAQojTGlzdE1vbml0b3JIVFRQUmVzcG9uc2VMb2dzUmVzcG9uc2USPAoEbG9ncxgBIAMoCzIuLm9wZW5zdGF0dXMubW9uaXRvci52MS5IVFRQUmVzcG9uc2VMb2dMaXN0SXRlbRJECgpwYWdpbmF0aW9uGAIgASgLMjAub3BlbnN0YXR1cy5tb25pdG9yLnYxLkhUVFBSZXNwb25zZUxvZ1BhZ2luYXRpb24iUAogR2V0TW9uaXRvckhUVFBSZXNwb25zZUxvZ1JlcXVlc3QSEwoCaWQYASABKAlCB7pIBHICEAESFwoGbG9nX2lkGAIgASgJQge6SARyAhABIl4KIUdldE1vbml0b3JIVFRQUmVzcG9uc2VMb2dSZXNwb25zZRI5CgNsb2cYASABKAsyLC5vcGVuc3RhdHVzLm1vbml0b3IudjEuSFRUUFJlc3BvbnNlTG9nRGV0YWlsKmEKCVRpbWVSYW5nZRIaChZUSU1FX1JBTkdFX1VOU1BFQ0lGSUVEEAASEQoNVElNRV9SQU5HRV8xRBABEhEKDVRJTUVfUkFOR0VfN0QQAhISCg5USU1FX1JBTkdFXzE0RBADKtkBChxIVFRQUmVzcG9uc2VMb2dSZXF1ZXN0U3RhdHVzEjAKLEhUVFBfUkVTUE9OU0VfTE9HX1JFUVVFU1RfU1RBVFVTX1VOU1BFQ0lGSUVEEAASLAooSFRUUF9SRVNQT05TRV9MT0dfUkVRVUVTVF9TVEFUVVNfU1VDQ0VTUxABEioKJkhUVFBfUkVTUE9OU0VfTE9HX1JFUVVFU1RfU1RBVFVTX0VSUk9SEAISLQopSFRUUF9SRVNQT05TRV9MT0dfUkVRVUVTVF9TVEFUVVNfREVHUkFERUQQAyqKAQoWSFRUUFJlc3BvbnNlTG9nVHJpZ2dlchIpCiVIVFRQX1JFU1BPTlNFX0xPR19UUklHR0VSX1VOU1BFQ0lGSUVEEAASIgoeSFRUUF9SRVNQT05TRV9MT0dfVFJJR0dFUl9DUk9OEAESIQodSFRUUF9SRVNQT05TRV9MT0dfVFJJR0dFUl9BUEkQAjKbFAoOTW9uaXRvclNlcnZpY2USuQMKEUNyZWF0ZUhUVFBNb25pdG9yEi8ub3BlbnN0YXR1cy5tb25pdG9yLnYxLkNyZWF0ZUhUVFBNb25pdG9yUmVxdWVzdBowLm9wZW5zdGF0dXMubW9uaXRvci52MS5DcmVhdGVIVFRQTW9uaXRvclJlc3BvbnNlIsACuke8Ahq5AkNyZWF0ZXMgYSBuZXcgSFRUUCBtb25pdG9yIGluIHRoZSBhdXRoZW50aWNhdGVkIHdvcmtzcGFjZS4gQ29uZmlndXJlIHRoZSB0YXJnZXQgVVJMLCBIVFRQIG1ldGhvZCwgcmVxdWVzdCBoZWFkZXJzIGFuZCBib2R5LCByZXNwb25zZSBhc3NlcnRpb25zIChzdGF0dXMgY29kZSwgYm9keSBjb250ZW50LCBoZWFkZXJzKSwgY2hlY2sgcGVyaW9kaWNpdHksIGdlb2dyYXBoaWMgcmVnaW9ucywgYW5kIG9wdGlvbmFsIE9wZW5UZWxlbWV0cnkgZXhwb3J0LiBUaGUgbW9uaXRvciBzdGFydHMgY2hlY2tpbmcgaW1tZWRpYXRlbHkgaWYgc2V0IHRvIGFjdGl2ZS4ScwoQQ3JlYXRlVENQTW9uaXRvchIuLm9wZW5zdGF0dXMubW9uaXRvci52MS5DcmVhdGVUQ1BNb25pdG9yUmVxdWVzdBovLm9wZW5zdGF0dXMubW9uaXRvci52MS5DcmVhdGVUQ1BNb25pdG9yUmVzcG9uc2UScwoQQ3JlYXRlRE5TTW9uaXRvchIuLm9wZW5zdGF0dXMubW9uaXRvci52MS5DcmVhdGVETlNNb25pdG9yUmVxdWVzdBovLm9wZW5zdGF0dXMubW9uaXRvci52MS5DcmVhdGVETlNNb25pdG9yUmVzcG9uc2USdgoRVXBkYXRlSFRUUE1vbml0b3ISLy5vcGVuc3RhdHVzLm1vbml0b3IudjEuVXBkYXRlSFRUUE1vbml0b3JSZXF1ZXN0GjAub3BlbnN0YXR1cy5tb25pdG9yLnYxLlVwZGF0ZUhUVFBNb25pdG9yUmVzcG9uc2UScwoQVXBkYXRlVENQTW9uaXRvchIuLm9wZW5zdGF0dXMubW9uaXRvci52MS5VcGRhdGVUQ1BNb25pdG9yUmVxdWVzdBovLm9wZW5zdGF0dXMubW9uaXRvci52MS5VcGRhdGVUQ1BNb25pdG9yUmVzcG9uc2UScwoQVXBkYXRlRE5TTW9uaXRvchIuLm9wZW5zdGF0dXMubW9uaXRvci52MS5VcGRhdGVETlNNb25pdG9yUmVxdWVzdBovLm9wZW5zdGF0dXMubW9uaXRvci52MS5VcGRhdGVETlNNb25pdG9yUmVzcG9uc2US6QIKDlRyaWdnZXJNb25pdG9yEiwub3BlbnN0YXR1cy5tb25pdG9yLnYxLlRyaWdnZXJNb25pdG9yUmVxdWVzdBotLm9wZW5zdGF0dXMubW9uaXRvci52MS5UcmlnZ2VyTW9uaXRvclJlc3BvbnNlIvkBukf1ARryAU1hbnVhbGx5IHRyaWdnZXJzIGFuIGltbWVkaWF0ZSBjaGVjayBmb3IgdGhlIHNwZWNpZmllZCBtb25pdG9yIGFjcm9zcyBhbGwgY29uZmlndXJlZCByZWdpb25zLiBUaGlzIG9wZXJhdGlvbiBpcyByYXRlLWxpbWl0ZWQgdW5kZXIgdGhlIHN5bnRoZXRpYy1jaGVja3MgcXVvdGEuIEEgbW9uaXRvciBydW4gcmVjb3JkIGlzIGNyZWF0ZWQgYW5kIHRoZSBjaGVjayBpcyBkaXNwYXRjaGVkIHRvIHRoZSBjaGVja2VyIHNlcnZpY2UuEmoKDURlbGV0ZU1vbml0b3ISKy5vcGVuc3RhdHVzLm1vbml0b3IudjEuRGVsZXRlTW9uaXRvclJlcXVlc3QaLC5vcGVuc3RhdHVzLm1vbml0b3IudjEuRGVsZXRlTW9uaXRvclJlc3BvbnNlEmwKDExpc3RNb25pdG9ycxIqLm9wZW5zdGF0dXMubW9uaXRvci52MS5MaXN0TW9uaXRvcnNSZXF1ZXN0Gisub3BlbnN0YXR1cy5tb25pdG9yLnYxLkxpc3RNb25pdG9yc1Jlc3BvbnNlIgOQAgESeAoQR2V0TW9uaXRvclN0YXR1cxIuLm9wZW5zdGF0dXMubW9uaXRvci52MS5HZXRNb25pdG9yU3RhdHVzUmVxdWVzdBovLm9wZW5zdGF0dXMubW9uaXRvci52MS5HZXRNb25pdG9yU3RhdHVzUmVzcG9uc2UiA5ACARKmAwoRR2V0TW9uaXRvclN1bW1hcnkSLy5vcGVuc3RhdHVzLm1vbml0b3IudjEuR2V0TW9uaXRvclN1bW1hcnlSZXF1ZXN0GjAub3BlbnN0YXR1cy5tb25pdG9yLnYxLkdldE1vbml0b3JTdW1tYXJ5UmVzcG9uc2UirQKQAgG6R6YCGqMCUmV0dXJucyBhZ2dyZWdhdGVkIG1ldHJpY3MgZm9yIGEgbW9uaXRvciBpbmNsdWRpbmcgbGF0ZW5jeSBwZXJjZW50aWxlcyAocDUwLCBwNzUsIHA5MCwgcDk1LCBwOTkpLCByZXF1ZXN0IGNvdW50cyBieSBzdGF0dXMgKHN1Y2Nlc3NmdWwsIGRlZ3JhZGVkLCBmYWlsZWQpLCBhbmQgdGhlIHRpbWVzdGFtcCBvZiB0aGUgbGFzdCBjaGVjay4gTWV0cmljcyBjYW4gYmUgc2NvcGVkIHRvIGEgdGltZSByYW5nZSAoMSBkYXksIDcgZGF5cywgb3IgMTQgZGF5cykgYW5kIGZpbHRlcmVkIGJ5IHNwZWNpZmljIHJlZ2lvbnMuEmYKCkdldE1vbml0b3ISKC5vcGVuc3RhdHVzLm1vbml0b3IudjEuR2V0TW9uaXRvclJlcXVlc3QaKS5vcGVuc3RhdHVzLm1vbml0b3IudjEuR2V0TW9uaXRvclJlc3BvbnNlIgOQAgESmQEKG0xpc3RNb25pdG9ySFRUUFJlc3BvbnNlTG9ncxI5Lm9wZW5zdGF0dXMubW9uaXRvci52MS5MaXN0TW9uaXRvckhUVFBSZXNwb25zZUxvZ3NSZXF1ZXN0Gjoub3BlbnN0YXR1cy5tb25pdG9yLnYxLkxpc3RNb25pdG9ySFRUUFJlc3BvbnNlTG9nc1Jlc3BvbnNlIgOQAgESkwEKGUdldE1vbml0b3JIVFRQUmVzcG9uc2VMb2cSNy5vcGVuc3RhdHVzLm1vbml0b3IudjEuR2V0TW9uaXRvckhUVFBSZXNwb25zZUxvZ1JlcXVlc3QaOC5vcGVuc3RhdHVzLm1vbml0b3IudjEuR2V0TW9uaXRvckhUVFBSZXNwb25zZUxvZ1Jlc3BvbnNlIgOQAgFCU1pRZ2l0aHViLmNvbS9vcGVuc3RhdHVzaHEvb3BlbnN0YXR1cy9wYWNrYWdlcy9wcm90by9vcGVuc3RhdHVzL21vbml0b3IvdjE7bW9uaXRvcnYxYgZwcm90bzM", 35 35 [ 36 36 file_buf_validate_validate, 37 37 file_gnostic_openapi_v3_annotations, ··· 861 861 messageDesc(file_openstatus_monitor_v1_service, 25); 862 862 863 863 /** 864 + * HTTPResponseLogTiming contains calculated timing phases in milliseconds. 865 + * 866 + * @generated from message openstatus.monitor.v1.HTTPResponseLogTiming 867 + */ 868 + export type HTTPResponseLogTiming = 869 + & Message<"openstatus.monitor.v1.HTTPResponseLogTiming"> 870 + & { 871 + /** 872 + * DNS lookup duration. 873 + * 874 + * @generated from field: int32 dns = 1; 875 + */ 876 + dns: number; 877 + 878 + /** 879 + * TCP connection duration. 880 + * 881 + * @generated from field: int32 connect = 2; 882 + */ 883 + connect: number; 884 + 885 + /** 886 + * TLS handshake duration. 887 + * 888 + * @generated from field: int32 tls = 3; 889 + */ 890 + tls: number; 891 + 892 + /** 893 + * Time to first byte duration. 894 + * 895 + * @generated from field: int32 ttfb = 4; 896 + */ 897 + ttfb: number; 898 + 899 + /** 900 + * Response transfer duration. 901 + * 902 + * @generated from field: int32 transfer = 5; 903 + */ 904 + transfer: number; 905 + }; 906 + 907 + /** 908 + * Describes the message openstatus.monitor.v1.HTTPResponseLogTiming. 909 + * Use `create(HTTPResponseLogTimingSchema)` to create a new message. 910 + */ 911 + export const HTTPResponseLogTimingSchema: GenMessage< 912 + HTTPResponseLogTiming 913 + > = /*@__PURE__*/ 914 + messageDesc(file_openstatus_monitor_v1_service, 26); 915 + 916 + /** 917 + * HTTPResponseLogListItem is a compact response log entry. 918 + * 919 + * @generated from message openstatus.monitor.v1.HTTPResponseLogListItem 920 + */ 921 + export type HTTPResponseLogListItem = 922 + & Message<"openstatus.monitor.v1.HTTPResponseLogListItem"> 923 + & { 924 + /** 925 + * Response log ID. 926 + * 927 + * @generated from field: optional string id = 1; 928 + */ 929 + id?: string; 930 + 931 + /** 932 + * Latency in milliseconds. 933 + * 934 + * @generated from field: int32 latency = 2; 935 + */ 936 + latency: number; 937 + 938 + /** 939 + * HTTP status code. 940 + * 941 + * @generated from field: optional int32 status_code = 3; 942 + */ 943 + statusCode?: number; 944 + 945 + /** 946 + * Monitor ID. 947 + * 948 + * @generated from field: string monitor_id = 4; 949 + */ 950 + monitorId: string; 951 + 952 + /** 953 + * Request status classification. 954 + * 955 + * @generated from field: openstatus.monitor.v1.HTTPResponseLogRequestStatus request_status = 5; 956 + */ 957 + requestStatus: HTTPResponseLogRequestStatus; 958 + 959 + /** 960 + * Region where the check ran. 961 + * 962 + * @generated from field: openstatus.monitor.v1.Region region = 6; 963 + */ 964 + region: Region; 965 + 966 + /** 967 + * Cron bucket timestamp in Unix milliseconds. 968 + * 969 + * @generated from field: int64 cron_timestamp = 7; 970 + */ 971 + cronTimestamp: bigint; 972 + 973 + /** 974 + * Check trigger. 975 + * 976 + * @generated from field: openstatus.monitor.v1.HTTPResponseLogTrigger trigger = 8; 977 + */ 978 + trigger: HTTPResponseLogTrigger; 979 + 980 + /** 981 + * Response timestamp in Unix milliseconds. 982 + * 983 + * @generated from field: int64 timestamp = 9; 984 + */ 985 + timestamp: bigint; 986 + 987 + /** 988 + * Timing phases. 989 + * 990 + * @generated from field: optional openstatus.monitor.v1.HTTPResponseLogTiming timing = 10; 991 + */ 992 + timing?: HTTPResponseLogTiming; 993 + }; 994 + 995 + /** 996 + * Describes the message openstatus.monitor.v1.HTTPResponseLogListItem. 997 + * Use `create(HTTPResponseLogListItemSchema)` to create a new message. 998 + */ 999 + export const HTTPResponseLogListItemSchema: GenMessage< 1000 + HTTPResponseLogListItem 1001 + > = /*@__PURE__*/ 1002 + messageDesc(file_openstatus_monitor_v1_service, 27); 1003 + 1004 + /** 1005 + * HTTPResponseLogDetail contains full response log debugging data. 1006 + * 1007 + * @generated from message openstatus.monitor.v1.HTTPResponseLogDetail 1008 + */ 1009 + export type HTTPResponseLogDetail = 1010 + & Message<"openstatus.monitor.v1.HTTPResponseLogDetail"> 1011 + & { 1012 + /** 1013 + * Compact response log fields. 1014 + * 1015 + * @generated from field: openstatus.monitor.v1.HTTPResponseLogListItem log = 1; 1016 + */ 1017 + log?: HTTPResponseLogListItem; 1018 + 1019 + /** 1020 + * Checked URL. 1021 + * 1022 + * @generated from field: string url = 2; 1023 + */ 1024 + url: string; 1025 + 1026 + /** 1027 + * Whether the check errored. 1028 + * 1029 + * @generated from field: bool error = 3; 1030 + */ 1031 + error: boolean; 1032 + 1033 + /** 1034 + * Error message, when present. 1035 + * 1036 + * @generated from field: optional string message = 4; 1037 + */ 1038 + message?: string; 1039 + 1040 + /** 1041 + * Redacted response headers. 1042 + * 1043 + * @generated from field: map<string, string> headers = 5; 1044 + */ 1045 + headers: { [key: string]: string }; 1046 + 1047 + /** 1048 + * Serialized assertions used for the check. 1049 + * 1050 + * @generated from field: optional string assertions = 6; 1051 + */ 1052 + assertions?: string; 1053 + }; 1054 + 1055 + /** 1056 + * Describes the message openstatus.monitor.v1.HTTPResponseLogDetail. 1057 + * Use `create(HTTPResponseLogDetailSchema)` to create a new message. 1058 + */ 1059 + export const HTTPResponseLogDetailSchema: GenMessage< 1060 + HTTPResponseLogDetail 1061 + > = /*@__PURE__*/ 1062 + messageDesc(file_openstatus_monitor_v1_service, 28); 1063 + 1064 + /** 1065 + * ListMonitorHTTPResponseLogsRequest is the request to list response logs within the 14-day HTTP response-log window. 1066 + * 1067 + * @generated from message openstatus.monitor.v1.ListMonitorHTTPResponseLogsRequest 1068 + */ 1069 + export type ListMonitorHTTPResponseLogsRequest = 1070 + & Message<"openstatus.monitor.v1.ListMonitorHTTPResponseLogsRequest"> 1071 + & { 1072 + /** 1073 + * Monitor ID to list response logs for (required). 1074 + * 1075 + * @generated from field: string id = 1; 1076 + */ 1077 + id: string; 1078 + 1079 + /** 1080 + * Start of the response log window as Unix milliseconds within the 14-day retention window. 1081 + * 1082 + * @generated from field: optional int64 from_timestamp = 2; 1083 + */ 1084 + fromTimestamp?: bigint; 1085 + 1086 + /** 1087 + * End of the response log window as Unix milliseconds within the 14-day retention window. 1088 + * 1089 + * @generated from field: optional int64 to_timestamp = 3; 1090 + */ 1091 + toTimestamp?: bigint; 1092 + 1093 + /** 1094 + * Maximum number of logs to return (1-100, defaults to 25). 1095 + * 1096 + * @generated from field: optional int32 limit = 4; 1097 + */ 1098 + limit?: number; 1099 + 1100 + /** 1101 + * Number of logs to skip for pagination (defaults to 0). 1102 + * 1103 + * @generated from field: optional int32 offset = 5; 1104 + */ 1105 + offset?: number; 1106 + }; 1107 + 1108 + /** 1109 + * Describes the message openstatus.monitor.v1.ListMonitorHTTPResponseLogsRequest. 1110 + * Use `create(ListMonitorHTTPResponseLogsRequestSchema)` to create a new message. 1111 + */ 1112 + export const ListMonitorHTTPResponseLogsRequestSchema: GenMessage< 1113 + ListMonitorHTTPResponseLogsRequest 1114 + > = /*@__PURE__*/ 1115 + messageDesc(file_openstatus_monitor_v1_service, 29); 1116 + 1117 + /** 1118 + * HTTPResponseLogPagination contains offset pagination metadata. 1119 + * 1120 + * @generated from message openstatus.monitor.v1.HTTPResponseLogPagination 1121 + */ 1122 + export type HTTPResponseLogPagination = 1123 + & Message<"openstatus.monitor.v1.HTTPResponseLogPagination"> 1124 + & { 1125 + /** 1126 + * Requested page size. 1127 + * 1128 + * @generated from field: int32 limit = 1; 1129 + */ 1130 + limit: number; 1131 + 1132 + /** 1133 + * Requested offset. 1134 + * 1135 + * @generated from field: int32 offset = 2; 1136 + */ 1137 + offset: number; 1138 + 1139 + /** 1140 + * Whether more logs are available. 1141 + * 1142 + * @generated from field: bool has_more = 3; 1143 + */ 1144 + hasMore: boolean; 1145 + 1146 + /** 1147 + * Next offset if more logs are available. 1148 + * 1149 + * @generated from field: optional int32 next_offset = 4; 1150 + */ 1151 + nextOffset?: number; 1152 + }; 1153 + 1154 + /** 1155 + * Describes the message openstatus.monitor.v1.HTTPResponseLogPagination. 1156 + * Use `create(HTTPResponseLogPaginationSchema)` to create a new message. 1157 + */ 1158 + export const HTTPResponseLogPaginationSchema: GenMessage< 1159 + HTTPResponseLogPagination 1160 + > = /*@__PURE__*/ 1161 + messageDesc(file_openstatus_monitor_v1_service, 30); 1162 + 1163 + /** 1164 + * ListMonitorHTTPResponseLogsResponse is the response containing response logs. 1165 + * 1166 + * @generated from message openstatus.monitor.v1.ListMonitorHTTPResponseLogsResponse 1167 + */ 1168 + export type ListMonitorHTTPResponseLogsResponse = 1169 + & Message<"openstatus.monitor.v1.ListMonitorHTTPResponseLogsResponse"> 1170 + & { 1171 + /** 1172 + * Response logs. 1173 + * 1174 + * @generated from field: repeated openstatus.monitor.v1.HTTPResponseLogListItem logs = 1; 1175 + */ 1176 + logs: HTTPResponseLogListItem[]; 1177 + 1178 + /** 1179 + * Pagination metadata. 1180 + * 1181 + * @generated from field: openstatus.monitor.v1.HTTPResponseLogPagination pagination = 2; 1182 + */ 1183 + pagination?: HTTPResponseLogPagination; 1184 + }; 1185 + 1186 + /** 1187 + * Describes the message openstatus.monitor.v1.ListMonitorHTTPResponseLogsResponse. 1188 + * Use `create(ListMonitorHTTPResponseLogsResponseSchema)` to create a new message. 1189 + */ 1190 + export const ListMonitorHTTPResponseLogsResponseSchema: GenMessage< 1191 + ListMonitorHTTPResponseLogsResponse 1192 + > = /*@__PURE__*/ 1193 + messageDesc(file_openstatus_monitor_v1_service, 31); 1194 + 1195 + /** 1196 + * GetMonitorHTTPResponseLogRequest is the request to get one response log. 1197 + * 1198 + * @generated from message openstatus.monitor.v1.GetMonitorHTTPResponseLogRequest 1199 + */ 1200 + export type GetMonitorHTTPResponseLogRequest = 1201 + & Message<"openstatus.monitor.v1.GetMonitorHTTPResponseLogRequest"> 1202 + & { 1203 + /** 1204 + * Monitor ID to get a response log for (required). 1205 + * 1206 + * @generated from field: string id = 1; 1207 + */ 1208 + id: string; 1209 + 1210 + /** 1211 + * Response log ID to retrieve (required). 1212 + * 1213 + * @generated from field: string log_id = 2; 1214 + */ 1215 + logId: string; 1216 + }; 1217 + 1218 + /** 1219 + * Describes the message openstatus.monitor.v1.GetMonitorHTTPResponseLogRequest. 1220 + * Use `create(GetMonitorHTTPResponseLogRequestSchema)` to create a new message. 1221 + */ 1222 + export const GetMonitorHTTPResponseLogRequestSchema: GenMessage< 1223 + GetMonitorHTTPResponseLogRequest 1224 + > = /*@__PURE__*/ 1225 + messageDesc(file_openstatus_monitor_v1_service, 32); 1226 + 1227 + /** 1228 + * GetMonitorHTTPResponseLogResponse is the response containing one response log. 1229 + * 1230 + * @generated from message openstatus.monitor.v1.GetMonitorHTTPResponseLogResponse 1231 + */ 1232 + export type GetMonitorHTTPResponseLogResponse = 1233 + & Message<"openstatus.monitor.v1.GetMonitorHTTPResponseLogResponse"> 1234 + & { 1235 + /** 1236 + * Response log details. 1237 + * 1238 + * @generated from field: openstatus.monitor.v1.HTTPResponseLogDetail log = 1; 1239 + */ 1240 + log?: HTTPResponseLogDetail; 1241 + }; 1242 + 1243 + /** 1244 + * Describes the message openstatus.monitor.v1.GetMonitorHTTPResponseLogResponse. 1245 + * Use `create(GetMonitorHTTPResponseLogResponseSchema)` to create a new message. 1246 + */ 1247 + export const GetMonitorHTTPResponseLogResponseSchema: GenMessage< 1248 + GetMonitorHTTPResponseLogResponse 1249 + > = /*@__PURE__*/ 1250 + messageDesc(file_openstatus_monitor_v1_service, 33); 1251 + 1252 + /** 864 1253 * TimeRange represents the time period for metrics aggregation. 865 1254 * 866 1255 * @generated from enum openstatus.monitor.v1.TimeRange ··· 902 1291 enumDesc(file_openstatus_monitor_v1_service, 0); 903 1292 904 1293 /** 1294 + * HTTPResponseLogRequestStatus is the result classification for an HTTP response log. 1295 + * 1296 + * @generated from enum openstatus.monitor.v1.HTTPResponseLogRequestStatus 1297 + */ 1298 + export enum HTTPResponseLogRequestStatus { 1299 + /** 1300 + * Unspecified request status. 1301 + * 1302 + * @generated from enum value: HTTP_RESPONSE_LOG_REQUEST_STATUS_UNSPECIFIED = 0; 1303 + */ 1304 + HTTP_RESPONSE_LOG_REQUEST_STATUS_UNSPECIFIED = 0, 1305 + 1306 + /** 1307 + * The monitor response satisfied its assertions. 1308 + * 1309 + * @generated from enum value: HTTP_RESPONSE_LOG_REQUEST_STATUS_SUCCESS = 1; 1310 + */ 1311 + HTTP_RESPONSE_LOG_REQUEST_STATUS_SUCCESS = 1, 1312 + 1313 + /** 1314 + * The monitor response failed its assertions or request. 1315 + * 1316 + * @generated from enum value: HTTP_RESPONSE_LOG_REQUEST_STATUS_ERROR = 2; 1317 + */ 1318 + HTTP_RESPONSE_LOG_REQUEST_STATUS_ERROR = 2, 1319 + 1320 + /** 1321 + * The monitor response was slower than the degraded threshold. 1322 + * 1323 + * @generated from enum value: HTTP_RESPONSE_LOG_REQUEST_STATUS_DEGRADED = 3; 1324 + */ 1325 + HTTP_RESPONSE_LOG_REQUEST_STATUS_DEGRADED = 3, 1326 + } 1327 + 1328 + /** 1329 + * Describes the enum openstatus.monitor.v1.HTTPResponseLogRequestStatus. 1330 + */ 1331 + export const HTTPResponseLogRequestStatusSchema: GenEnum< 1332 + HTTPResponseLogRequestStatus 1333 + > = /*@__PURE__*/ 1334 + enumDesc(file_openstatus_monitor_v1_service, 1); 1335 + 1336 + /** 1337 + * HTTPResponseLogTrigger describes what started the monitor check. 1338 + * 1339 + * @generated from enum openstatus.monitor.v1.HTTPResponseLogTrigger 1340 + */ 1341 + export enum HTTPResponseLogTrigger { 1342 + /** 1343 + * Unspecified trigger. 1344 + * 1345 + * @generated from enum value: HTTP_RESPONSE_LOG_TRIGGER_UNSPECIFIED = 0; 1346 + */ 1347 + HTTP_RESPONSE_LOG_TRIGGER_UNSPECIFIED = 0, 1348 + 1349 + /** 1350 + * Scheduled monitor run. 1351 + * 1352 + * @generated from enum value: HTTP_RESPONSE_LOG_TRIGGER_CRON = 1; 1353 + */ 1354 + HTTP_RESPONSE_LOG_TRIGGER_CRON = 1, 1355 + 1356 + /** 1357 + * API-triggered monitor run. 1358 + * 1359 + * @generated from enum value: HTTP_RESPONSE_LOG_TRIGGER_API = 2; 1360 + */ 1361 + HTTP_RESPONSE_LOG_TRIGGER_API = 2, 1362 + } 1363 + 1364 + /** 1365 + * Describes the enum openstatus.monitor.v1.HTTPResponseLogTrigger. 1366 + */ 1367 + export const HTTPResponseLogTriggerSchema: GenEnum< 1368 + HTTPResponseLogTrigger 1369 + > = /*@__PURE__*/ 1370 + enumDesc(file_openstatus_monitor_v1_service, 2); 1371 + 1372 + /** 905 1373 * MonitorService provides CRUD and operational commands for monitors. 906 1374 * 907 1375 * @generated from service openstatus.monitor.v1.MonitorService ··· 1027 1495 methodKind: "unary"; 1028 1496 input: typeof GetMonitorRequestSchema; 1029 1497 output: typeof GetMonitorResponseSchema; 1498 + }; 1499 + /** 1500 + * ListMonitorHTTPResponseLogs returns paginated response logs for an HTTP monitor from the 14-day HTTP response-log window. 1501 + * 1502 + * @generated from rpc openstatus.monitor.v1.MonitorService.ListMonitorHTTPResponseLogs 1503 + */ 1504 + listMonitorHTTPResponseLogs: { 1505 + methodKind: "unary"; 1506 + input: typeof ListMonitorHTTPResponseLogsRequestSchema; 1507 + output: typeof ListMonitorHTTPResponseLogsResponseSchema; 1508 + }; 1509 + /** 1510 + * GetMonitorHTTPResponseLog returns one response log for an HTTP monitor. 1511 + * 1512 + * @generated from rpc openstatus.monitor.v1.MonitorService.GetMonitorHTTPResponseLog 1513 + */ 1514 + getMonitorHTTPResponseLog: { 1515 + methodKind: "unary"; 1516 + input: typeof GetMonitorHTTPResponseLogRequestSchema; 1517 + output: typeof GetMonitorHTTPResponseLogResponseSchema; 1030 1518 }; 1031 1519 }> = /*@__PURE__*/ 1032 1520 serviceDesc(file_openstatus_monitor_v1_service, 0);
+15 -1
src/mod.ts
··· 92 92 CreateTCPMonitorResponse, 93 93 DeleteMonitorRequest, 94 94 DeleteMonitorResponse, 95 + GetMonitorHTTPResponseLogRequest, 96 + GetMonitorHTTPResponseLogResponse, 95 97 GetMonitorStatusRequest, 96 98 GetMonitorStatusResponse, 97 99 GetMonitorSummaryRequest, 98 100 GetMonitorSummaryResponse, 101 + HTTPResponseLogDetail, 102 + HTTPResponseLogListItem, 103 + HTTPResponseLogPagination, 104 + HTTPResponseLogTiming, 105 + ListMonitorHTTPResponseLogsRequest, 106 + ListMonitorHTTPResponseLogsResponse, 99 107 ListMonitorsRequest, 100 108 ListMonitorsResponse, 101 109 RegionStatus, ··· 109 117 UpdateTCPMonitorResponse, 110 118 } from "./gen/openstatus/monitor/v1/service_pb.ts"; 111 119 112 - export { TimeRange } from "./gen/openstatus/monitor/v1/service_pb.ts"; 120 + export { 121 + HTTPResponseLogRequestStatus, 122 + HTTPResponseLogTrigger, 123 + TimeRange, 124 + } from "./gen/openstatus/monitor/v1/service_pb.ts"; 113 125 114 126 // Re-export health types 115 127 export type { ··· 347 359 * - `deleteMonitor` - Delete a monitor 348 360 * - `getMonitorStatus` - Get status of all regions for a monitor 349 361 * - `getMonitorSummary` - Get aggregated metrics for a monitor 362 + * - `listMonitorHTTPResponseLogs` - List HTTP response logs for a monitor 363 + * - `getMonitorHTTPResponseLog` - Get a single HTTP response log with full details 350 364 */ 351 365 MonitorService: Client<typeof MonitorService>; 352 366 };