| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.listTags = void 0;
- /*
- * This is a TypeScript port of the original Java version, which was written by
- * Gil Tene as described in
- * https://github.com/HdrHistogram/HdrHistogram
- * and released to the public domain, as explained at
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
- const Histogram_1 = require("./Histogram");
- const encoding_1 = require("./encoding");
- const TAG_PREFIX = "Tag=";
- const TAG_PREFIX_LENGTH = "Tag=".length;
- /**
- * A histogram log reader.
- * <p>
- * Histogram logs are used to capture full fidelity, per-time-interval
- * histograms of a recorded value.
- * <p>
- * For example, a histogram log can be used to capture high fidelity
- * reaction-time logs for some measured system or subsystem component.
- * Such a log would capture a full reaction time histogram for each
- * logged interval, and could be used to later reconstruct a full
- * HdrHistogram of the measured reaction time behavior for any arbitrary
- * time range within the log, by adding [only] the relevant interval
- * histograms.
- * <h3>Histogram log format:</h3>
- * A histogram log file consists of text lines. Lines beginning with
- * the "#" character are optional and treated as comments. Lines
- * containing the legend (starting with "Timestamp") are also optional
- * and ignored in parsing the histogram log. All other lines must
- * be valid interval description lines. Text fields are delimited by
- * commas, spaces.
- * <p>
- * A valid interval description line contains an optional Tag=tagString
- * text field, followed by an interval description.
- * <p>
- * A valid interval description must contain exactly four text fields:
- * <ul>
- * <li>StartTimestamp: The first field must contain a number parse-able as a Double value,
- * representing the start timestamp of the interval in seconds.</li>
- * <li>intervalLength: The second field must contain a number parse-able as a Double value,
- * representing the length of the interval in seconds.</li>
- * <li>Interval_Max: The third field must contain a number parse-able as a Double value,
- * which generally represents the maximum value of the interval histogram.</li>
- * <li>Interval_Compressed_Histogram: The fourth field must contain a text field
- * parse-able as a Base64 text representation of a compressed HdrHistogram.</li>
- * </ul>
- * The log file may contain an optional indication of a starting time. Starting time
- * is indicated using a special comments starting with "#[StartTime: " and followed
- * by a number parse-able as a double, representing the start time (in seconds)
- * that may be added to timestamps in the file to determine an absolute
- * timestamp (e.g. since the epoch) for each interval.
- */
- class HistogramLogReader {
- constructor(logContent, bitBucketSize = 32, useWebAssembly = false) {
- this.lines = splitLines(logContent);
- this.currentLineIndex = 0;
- this.bitBucketSize = bitBucketSize;
- this.useWebAssembly = useWebAssembly;
- }
- /**
- * Read the next interval histogram from the log. Returns a Histogram object if
- * an interval line was found, or null if not.
- * <p>Upon encountering any unexpected format errors in reading the next interval
- * from the file, this method will return a null.
- * @return a DecodedInterval, or a null if no appropriate interval found
- */
- nextIntervalHistogram(rangeStartTimeSec = 0, rangeEndTimeSec = Number.MAX_VALUE) {
- while (this.currentLineIndex < this.lines.length) {
- const currentLine = this.lines[this.currentLineIndex];
- this.currentLineIndex++;
- if (currentLine.startsWith("#[StartTime:")) {
- this.parseStartTimeFromLine(currentLine);
- }
- else if (currentLine.startsWith("#[BaseTime:")) {
- this.parseBaseTimeFromLine(currentLine);
- }
- else if (currentLine.startsWith("#") ||
- currentLine.startsWith('"StartTimestamp"')) {
- // skip legend & meta data for now
- }
- else if (currentLine.includes(",")) {
- const tokens = currentLine.split(",");
- const [firstToken] = tokens;
- let tag;
- if (firstToken.startsWith(TAG_PREFIX)) {
- tag = firstToken.substring(TAG_PREFIX_LENGTH);
- tokens.shift();
- }
- else {
- tag = Histogram_1.NO_TAG;
- }
- const [rawLogTimeStampInSec, rawIntervalLengthSec, , base64Histogram,] = tokens;
- const logTimeStampInSec = Number.parseFloat(rawLogTimeStampInSec);
- if (!this.baseTimeSec) {
- // No explicit base time noted. Deduce from 1st observed time (compared to start time):
- if (logTimeStampInSec < this.startTimeSec - 365 * 24 * 3600.0) {
- // Criteria Note: if log timestamp is more than a year in the past (compared to
- // StartTime), we assume that timestamps in the log are not absolute
- this.baseTimeSec = this.startTimeSec;
- }
- else {
- // Timestamps are absolute
- this.baseTimeSec = 0.0;
- }
- }
- if (rangeEndTimeSec < logTimeStampInSec) {
- return null;
- }
- if (logTimeStampInSec < rangeStartTimeSec) {
- continue;
- }
- const histogram = encoding_1.decodeFromCompressedBase64(base64Histogram, this.bitBucketSize, this.useWebAssembly);
- histogram.startTimeStampMsec =
- (this.baseTimeSec + logTimeStampInSec) * 1000;
- const intervalLengthSec = Number.parseFloat(rawIntervalLengthSec);
- histogram.endTimeStampMsec =
- (this.baseTimeSec + logTimeStampInSec + intervalLengthSec) * 1000;
- histogram.tag = tag;
- return histogram;
- }
- }
- return null;
- }
- parseStartTimeFromLine(line) {
- this.startTimeSec = Number.parseFloat(line.split(" ")[1]);
- }
- parseBaseTimeFromLine(line) {
- this.baseTimeSec = Number.parseFloat(line.split(" ")[1]);
- }
- }
- const splitLines = (logContent) => logContent.split(/\r\n|\r|\n/g);
- const shouldIncludeNoTag = (lines) => lines.find((line) => !line.startsWith("#") &&
- !line.startsWith('"') &&
- !line.startsWith(TAG_PREFIX) &&
- line.includes(","));
- exports.listTags = (content) => {
- const lines = splitLines(content);
- const tags = lines
- .filter((line) => line.includes(",") && line.startsWith(TAG_PREFIX))
- .map((line) => line.substring(TAG_PREFIX_LENGTH, line.indexOf(",")));
- const tagsWithoutDuplicates = new Set(tags);
- const result = Array.from(tagsWithoutDuplicates);
- if (shouldIncludeNoTag(lines)) {
- result.unshift("NO TAG");
- }
- return result;
- };
- exports.default = HistogramLogReader;
- //# sourceMappingURL=HistogramLogReader.js.map
|