ServerTiming.js 3.3 KB

123456789101112131415161718192021222324252627
  1. export default class ServerTiming{constructor(metric,value,description){this.metric=metric;this.value=value;this.description=description;}
  2. static parseHeaders(headers){const rawServerTimingHeaders=headers.filter(item=>item.name.toLowerCase()==='server-timing');if(!rawServerTimingHeaders.length){return null;}
  3. const serverTimings=rawServerTimingHeaders.reduce((memo,header)=>{const timing=this.createFromHeaderValue(header.value);memo.pushAll(timing.map(function(entry){return new ServerTiming(entry.name,entry.hasOwnProperty('dur')?entry.dur:null,entry.hasOwnProperty('desc')?entry.desc:'');}));return memo;},[]);serverTimings.sort((a,b)=>a.metric.toLowerCase().compareTo(b.metric.toLowerCase()));return serverTimings;}
  4. static createFromHeaderValue(valueString){function trimLeadingWhiteSpace(){valueString=valueString.replace(/^\s*/,'');}
  5. function consumeDelimiter(char){console.assert(char.length===1);trimLeadingWhiteSpace();if(valueString.charAt(0)!==char){return false;}
  6. valueString=valueString.substring(1);return true;}
  7. function consumeToken(){const result=/^(?:\s*)([\w!#$%&'*+\-.^`|~]+)(?:\s*)(.*)/.exec(valueString);if(!result){return null;}
  8. valueString=result[2];return result[1];}
  9. function consumeTokenOrQuotedString(){trimLeadingWhiteSpace();if(valueString.charAt(0)==='"'){return consumeQuotedString();}
  10. return consumeToken();}
  11. function consumeQuotedString(){console.assert(valueString.charAt(0)==='"');valueString=valueString.substring(1);let value='';while(valueString.length){const result=/^([^"\\]*)(.*)/.exec(valueString);value+=result[1];if(result[2].charAt(0)==='"'){valueString=result[2].substring(1);return value;}
  12. console.assert(result[2].charAt(0)==='\\');value+=result[2].charAt(1);valueString=result[2].substring(2);}
  13. return null;}
  14. function consumeExtraneous(){const result=/([,;].*)/.exec(valueString);if(result){valueString=result[1];}}
  15. const result=[];let name;while((name=consumeToken())!==null){const entry={name};if(valueString.charAt(0)==='='){this.showWarning(ls`Deprecated syntax found. Please use: <name>;dur=<duration>;desc=<description>`);}
  16. while(consumeDelimiter(';')){let paramName;if((paramName=consumeToken())===null){continue;}
  17. paramName=paramName.toLowerCase();const parseParameter=this.getParserForParameter(paramName);let paramValue=null;if(consumeDelimiter('=')){paramValue=consumeTokenOrQuotedString();consumeExtraneous();}
  18. if(parseParameter){if(entry.hasOwnProperty(paramName)){this.showWarning(ls`Duplicate parameter \"${paramName}\" ignored.`);continue;}
  19. if(paramValue===null){this.showWarning(ls`No value found for parameter \"${paramName}\".`);}
  20. parseParameter.call(this,entry,paramValue);}else{this.showWarning(ls`Unrecognized parameter \"${paramName}\".`);}}
  21. result.push(entry);if(!consumeDelimiter(',')){break;}}
  22. if(valueString.length){this.showWarning(ls`Extraneous trailing characters.`);}
  23. return result;}
  24. static getParserForParameter(paramName){switch(paramName){case'dur':return function(entry,paramValue){entry.dur=0;if(paramValue!==null){const duration=parseFloat(paramValue);if(isNaN(duration)){this.showWarning(ls`Unable to parse \"${paramName}\" value \"${paramValue}\".`);return;}
  25. entry.dur=duration;}};case'desc':return function(entry,paramValue){entry.desc=paramValue||'';};default:return null;}}
  26. static showWarning(msg){Common.console.warn(Common.UIString(`ServerTiming: ${msg}`));}}
  27. self.SDK=self.SDK||{};SDK=SDK||{};SDK.ServerTiming=ServerTiming;