| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 Copyright 2016 The LUCI Authors. All rights reserved. | |
| 3 Use of this source code is governed under the Apache License, Version 2.0 | |
| 4 that can be found in the LICENSE file. | |
| 5 */ | |
| 6 | |
| 7 export module LogDog { | |
| 8 /** Locally-typed LogStreamDescriptor class. */ | |
| 9 export interface LogStreamDescriptor { | |
| 10 readonly timestamp: Date; | |
| 11 } | |
| 12 | |
| 13 export function makeLogStreamDescriptor(desc: any): LogStreamDescriptor { | |
| 14 desc.timestamp = new Date(desc.timestamp); | |
| 15 return desc; | |
| 16 } | |
| 17 | |
| 18 export interface LogStreamState { | |
| 19 created: Date; | |
| 20 terminalIndex: number; | |
| 21 archive: { | |
| 22 | |
| 23 }; | |
| 24 } | |
| 25 | |
| 26 export function makeLogStreamState(state: any): LogStreamState { | |
| 27 state.created = new Date(state.created); | |
| 28 state.terminalIndex = int64(state.terminalIndex); | |
| 29 return state; | |
| 30 } | |
| 31 | |
| 32 /** Locally-typed LogEntry class. */ | |
| 33 export type LogEntry = { | |
| 34 prefixIndex: number; | |
| 35 streamIndex: number; | |
| 36 timeOffset: number; | |
| 37 | |
| 38 desc: LogStreamDescriptor | null; | |
| 39 timestamp: Date | null; | |
| 40 | |
| 41 text?: { | |
| 42 lines?: { | |
| 43 value?: string; | |
| 44 delimiter?: string; | |
| 45 }[]; | |
| 46 }; | |
| 47 } | |
| 48 | |
| 49 export function makeLogEntry(le: any, desc: LogStreamDescriptor): LogEntry { | |
| 50 le.timeOffset = durationProtoToMillis(le.timeOffset); | |
| 51 le.prefixIndex = int64(le.prefixIndex); | |
| 52 le.streamIndex = int64(le.streamIndex); | |
| 53 | |
| 54 if (desc) { | |
| 55 le.desc = desc; | |
| 56 le.timestamp = addMillisecondsToDate(desc.timestamp, le.timeOffset); | |
| 57 } | |
| 58 return le; | |
| 59 } | |
| 60 | |
| 61 /** A log stream project/path qualifier. */ | |
| 62 export class Stream { | |
| 63 constructor(readonly project: string, readonly path: string) {} | |
| 64 | |
| 65 fullName(): string { | |
| 66 return this.project + "/" + this.path; | |
| 67 } | |
| 68 | |
| 69 get prefix(): string { | |
| 70 let sepIdx = this.path.indexOf("/+"); | |
| 71 if (sepIdx > 0) { | |
| 72 return this.path.substring(0, sepIdx); | |
| 73 } | |
| 74 return this.path; | |
| 75 } | |
| 76 | |
| 77 get name(): string { | |
| 78 const sep = "/+/"; | |
| 79 let sepIdx = this.path.indexOf(sep); | |
| 80 if (sepIdx < 0) { | |
| 81 return ""; | |
| 82 } | |
| 83 return this.path.substring(sepIdx + sep.length); | |
| 84 } | |
| 85 | |
| 86 samePrefixAs(other: Stream): boolean { | |
| 87 return ( | |
| 88 (this.project === other.project) && | |
| 89 (this.prefix === other.prefix)); | |
| 90 } | |
| 91 | |
| 92 static splitProject(v: string): Stream { | |
| 93 let parts = Stream.split(v, 2); | |
| 94 if (parts.length === 1) { | |
| 95 return new Stream(v, ""); | |
| 96 } | |
| 97 return new Stream(parts[0], parts[1]); | |
| 98 } | |
| 99 | |
| 100 static split = function(v: string, count: number): string[] { | |
| 101 let parts = v.split("/"); | |
| 102 if (!count) { | |
| 103 return parts; | |
| 104 } | |
| 105 let result = parts.splice(0, count-1); | |
| 106 if (parts.length) { | |
| 107 result.push(parts.join("/")); | |
| 108 } | |
| 109 return result; | |
| 110 }; | |
| 111 | |
| 112 static cmp(a: Stream, b: Stream): number { | |
| 113 if (a.project < b.project) { | |
| 114 return -1; | |
| 115 } | |
| 116 if (a.project > b.project) { | |
| 117 return 1; | |
| 118 } | |
| 119 return (a.path < b.path) ? -1 : ((a.path > b.path) ? 1 : 0); | |
| 120 }; | |
| 121 } | |
| 122 | |
| 123 /** | |
| 124 * Converts a string int64 into a Javascript number. | |
| 125 * | |
| 126 * Note that Javascript cannot hold a value larger than 2^53-1. If log streams | |
| 127 * ever approach this length, we will need to rework this value as an integer- | |
| 128 * string with helper functions. | |
| 129 */ | |
| 130 function int64(s: string): number { | |
| 131 if (!s) { | |
| 132 return 0; | |
| 133 } | |
| 134 | |
| 135 let value = parseInt(s, 10); | |
| 136 if (isNaN(value)) { | |
| 137 throw new Error("Value is not a number: " + s); | |
| 138 } | |
| 139 return value; | |
| 140 } | |
| 141 | |
| 142 /** | |
| 143 * Adds a specified duration protobuf to the supplied Date. | |
| 144 * | |
| 145 * Duration protos are expressed as a string referencing a floating point | |
| 146 * number of seconds followed by the letter "s": | |
| 147 * - "1337s" | |
| 148 * - "3.141592s" | |
| 149 */ | |
| 150 function durationProtoToMillis(value: string): number { | |
| 151 if ((!value) || value.charAt(value.length - 1) !== "s") { | |
| 152 throw new Error("Seconds string does not end in 's': " + value); | |
| 153 } | |
| 154 return (parseFloat(value) * 1000.0); | |
| 155 } | |
| 156 | |
| 157 /** | |
| 158 * Returns a new Date object whose value is the initial date object with the | |
| 159 * specified number of milliseconds added to it. | |
| 160 * | |
| 161 * @param d {Date} The base Date object. | |
| 162 * @param ms {Number} The number of milliseconds to add. | |
| 163 */ | |
| 164 function addMillisecondsToDate(d: Date, ms: number) { | |
| 165 d = new Date(d); | |
| 166 d.setMilliseconds(d.getMilliseconds() + ms); | |
| 167 return d; | |
| 168 } | |
| 169 } | |
| OLD | NEW |