Skip to content

Instantly share code, notes, and snippets.

@mseeley
Created March 15, 2014 16:44
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mseeley/9570215 to your computer and use it in GitHub Desktop.
Save mseeley/9570215 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>Timeline</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
</head>
<body>
<p>This is a basic example of creating your own Timeline for viewing in the Web Inspector Timeline view.</p>
<p>Save the string logged to the console in a JSON file. Then load into the Timeline.</p>
</body>
<script src="Timeline.js"></script>
<script>
var timeline = new Timeline(),
startup = timeline.mark('startup'),
loadApplicationState = timeline.mark('load application state'),
initializeStateMark = timeline.mark('initialize application state'),
persistApplicationState = timeline.mark('persist application state'),
renderLandingMark = timeline.mark('render landing page');
startup.begin();
// Use a series of timeouts to mimic async activity
loadApplicationState.begin();
setTimeout(function () {
loadApplicationState.end();
persistApplicationState.begin();
setTimeout(persistApplicationState.end.bind(persistApplicationState), 200);
initializeStateMark.begin();
setTimeout(function () {
initializeStateMark.end();
renderLandingMark.begin();
setTimeout(function () {
renderLandingMark.end();
startup.end();
// Post the timeline.data
console.log(JSON.stringify(timeline.data));
}, 500);
}, 1000)
}, 1500);
</script>
</html>
/*
* This is a bespoke Timeline of manually instrumented Timestamp objects.
* More format information is available at:
* https://github.com/WebKit/webkit/blob/master/Source/WebInspectorUI/Versions/Inspector-iOS-7.0.json
* https://github.com/WebKit/webkit/blob/master/Source/WebCore/inspector/InspectorTimelineAgent.cpp
*/
var Timeline = (function () {
var TIME_STAMP = 'TimeStamp';
/**
* The TimeStamp class encapsulates information on a single TimeStamp object.
* @param {String} the message displayed in the 'RESULTS' Timeline column
*/
function TimeStamp (message) {
this.message = message;
}
TimeStamp.prototype = Object.create(
Object.prototype,
{
_start: {
writable: true,
value: null
},
_end: {
writable: true,
value: null
},
/**
* The message displayed in the 'RESULTS' Timeline column.
* @type {String}
*/
message: {
enumerable: true,
writable: true,
configurable: true,
value: '',
},
/**
* This TimeStamp formatted at a Timeline data object
* @type {Object}
*/
data: {
get: function () {
return this.ended === false ?
null :
{
type: TIME_STAMP,
startTime: this._start,
endTime: this._end,
data: {
message: this.message
}
};
}
},
/**
* True if the TimeStamp has been ended, false otherwise.
* @type {Boolean}
*/
ended: {
enumerable: true,
get: function () {
return this._start !== null && this._end !== null;
}
},
/**
* Records the starting time of a TimeStamp
* @type {Function}
* @return {void}
*/
begin: {
value: function () {
if (this._start === null) {
this._start = Date.now();
}
}
},
/**
* Records the ending time of a TimeStamp
* @type {Function}
* @return {void}
*/
end: {
value: function () {
var now;
if (this._end === null) {
now = Date.now();
if (this._start === null) {
this._start = now;
}
this._end = now;
}
}
}
}
);
/**
* Timeline is a simple class which
* @param {String} [userAgent] The user agent which owns the records.
* Defaults to `navigator.userAgent`
*/
function Timeline (userAgent) {
this._userAgent = userAgent || navigator.userAgent;
this._items = [];
}
Timeline.prototype = Object.create(
Object.prototype,
{
_userAgent: {
writable: true,
value: null
},
_items: {
writable: true,
value: null
},
/**
* Returns this Timeline composed of all ended items in the correct
* format for the Timeline view. You can call access this data
* many times to keep a running count of activities.
* @type {Object}
*/
data: {
get: function () {
var data = this._items.
filter(this._itemIsEnded).
map(this._dataForItem);
data.sort(this._sortItemStartTimes);
return [this._userAgent].concat(data);
}
},
/**
* A factory which constructs a Timeline object from the provided
* arguments.
* @type {Function}
* @return {Object}
*/
mark: {
value: function (message) {
var ts = new TimeStamp(message);
this._items.push(ts);
return ts;
}
},
/**
* Removes tracking of all Timeline items. Call this method to
* reuse a single Timeline instance.
* @type {Function}
* @return {void}
*/
clear: {
value: function () {
this._items = [];
}
},
_itemIsEnded: {
value: function (item) {
return item.ended === true;
}
},
_dataForItem: {
value: function (item) {
return item.data;
}
},
_sortItemStartTimes: {
value: function (a, b) {
var i = 0;
if (a.startTime < b.startTime) {
i = -1;
} else if (a.startTime > b.startTime) {
i = 1;
} else {
i = a.endTime <= b.endTime ? -1 : 1;
}
return i;
}
}
}
);
return Timeline;
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment