blob: d2167fb140e2aa0d5cb62e71cc2f07b66efc255d [file] [log] [blame]
library input.transformer;
import 'dart:convert';
import 'instrumentation_input_converter.dart';
import 'operation.dart';
final int NINE = '9'.codeUnitAt(0);
final int ZERO = '0'.codeUnitAt(0);
/**
* [InputConverter] converts an input stream
* into a series of operations to be sent to the analysis server.
* The input stream can be either an instrumenation or log file.
*/
class InputConverter extends Converter<String, Operation> {
/**
* The number of lines read before the underlying converter was determined
* or the end of file was reached.
*/
int headerLineCount = 0;
/**
* The underlying converter used to translate lines into operations
* or `null` if it has not yet been determined.
*/
Converter<String, Operation> converter;
@override
Operation convert(String line) {
if (converter != null) {
return converter.convert(line);
}
if (headerLineCount == 20) {
throw 'Failed to determine input file format';
}
if (InstrumentationInputConverter.isFormat(line)) {
converter = new InstrumentationInputConverter();
} else if (LogFileInputConverter.isFormat(line)) {
converter = new LogFileInputConverter();
}
if (converter != null) {
return converter.convert(line);
}
print(line);
return null;
}
@override
_InputSink startChunkedConversion(outSink) {
return new _InputSink(this, outSink);
}
}
/**
* [LogFileInputConverter] converts a log file stream
* into a series of operations to be sent to the analysis server.
*/
class LogFileInputConverter extends Converter<String, Operation> {
@override
Operation convert(String line) {
throw 'not implemented yet';
}
/**
* Determine if the given line is from an instrumentation file.
* For example:
* `1428347977499 <= {"event":"server.connected","params":{"version":"1.6.0"}}`
*/
static bool isFormat(String line) {
String timeStampString = _parseTimeStamp(line);
int start = timeStampString.length;
int end = start + 5;
return start > 10 &&
line.length > end &&
line.substring(start, end) == ' <= {"event":"server.connected"';
}
/**
* Parse the given line and return the millisecond timestamp or `null`
* if it cannot be determined.
*/
static String _parseTimeStamp(String line) {
int index = 0;
while (index < line.length) {
int code = line.codeUnitAt(index);
if (code < ZERO || NINE < code) {
return line.substring(0, index);
}
++index;
}
return line;
}
}
class _InputSink extends ChunkedConversionSink<String> {
final Converter<String, Operation> converter;
final outSink;
_InputSink(this.converter, this.outSink);
@override
void add(String line) {
Operation op = converter.convert(line);
if (op != null) {
outSink.add(op);
}
}
@override
void close() {
outSink.close();
}
}