diff --git a/packages/mockotlpserver/CHANGELOG.md b/packages/mockotlpserver/CHANGELOG.md index 92854071..7f18e446 100644 --- a/packages/mockotlpserver/CHANGELOG.md +++ b/packages/mockotlpserver/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +- feat: Some improvements to "summary" styling. + - Show attributes for histogram metrics and handle showing multiple data points. + - Bold "span", "event", "$metricType" in renderings, and style the name of that + span/event/metric in magenta. See PR for screenshots. - fix: Don't throw printing a metrics summary for a histogram without attributes. ## v0.5.0 diff --git a/packages/mockotlpserver/lib/logs-summary.js b/packages/mockotlpserver/lib/logs-summary.js index b380ee8e..0e0b0c6c 100644 --- a/packages/mockotlpserver/lib/logs-summary.js +++ b/packages/mockotlpserver/lib/logs-summary.js @@ -27,38 +27,7 @@ const {hrTimeToTimeStamp, millisToHrTime} = require('@opentelemetry/core'); const {Printer} = require('./printers'); const {normalizeLogs} = require('./normalize'); - -// This color-related block from Bunyan, with permission. ;) -// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics -// Suggested colors (some are unreadable in common cases): -// - Good: cyan, yellow (limited use), bold, green, magenta, red -// - Bad: blue (not visible on cmd.exe), grey (same color as background on -// Solarized Dark theme from , see -// issue #160) -var colors = { - bold: [1, 22], - italic: [3, 23], - underline: [4, 24], - inverse: [7, 27], - white: [37, 39], - grey: [90, 39], - black: [30, 39], - blue: [34, 39], - cyan: [36, 39], - green: [32, 39], - magenta: [35, 39], - red: [31, 39], - yellow: [33, 39], -}; -function stylizeWithColor(str, color) { - if (!str) return ''; - var codes = colors[color]; - if (codes) { - return '\x1b[' + codes[0] + 'm' + str + '\x1b[' + codes[1] + 'm'; - } else { - return str; - } -} +const {style} = require('./styling'); class LogsSummaryPrinter extends Printer { /** @@ -107,15 +76,15 @@ class LogsSummaryPrinter extends Printer { let lead = `[${time}] ${sev} (${meta}):`; let bodyInLead = false; if (isEvent) { - lead += ` Event ${stylizeWithColor( + lead += ` ${style('event', 'bold')} "${style( rec.attributes['event.name'], 'magenta' - )}`; + )}"`; } else if ( typeof rec.body === 'string' && rec.body.indexOf('\n') === -1 ) { - lead += ' ' + stylizeWithColor(rec.body, 'cyan'); + lead += ' ' + style(rec.body, 'cyan'); bodyInLead = true; } rendering.push(lead); @@ -125,7 +94,7 @@ class LogsSummaryPrinter extends Printer { // pass } else if (typeof rec.body === 'string') { rendering.push( - stylizeWithColor( + style( ' ' + rec.body.split(/\n/).join('\n '), 'cyan' ) diff --git a/packages/mockotlpserver/lib/metrics-summary.js b/packages/mockotlpserver/lib/metrics-summary.js index e00efa84..8efe4d1b 100644 --- a/packages/mockotlpserver/lib/metrics-summary.js +++ b/packages/mockotlpserver/lib/metrics-summary.js @@ -23,8 +23,11 @@ * Dev Notes / Ideas: */ +const util = require('util'); + const {Printer} = require('./printers'); const {normalizeMetrics} = require('./normalize'); +const {style} = require('./styling'); class MetricsSummaryPrinter extends Printer { printMetrics(rawMetrics) { @@ -41,34 +44,46 @@ class MetricsSummaryPrinter extends Printer { scopes.push(scope); for (let metric of scopeMetric.metrics) { if (metric.histogram) { - // TODO do we want to attempt a short summary of histogram buckets? - // TODO handle multiple datapoints, dp per normalized attribute set. Highest prio. Run `node -r @elastic/opentelemetry-node http-server.js` for example data. - if (metric.histogram.dataPoints.length !== 1) { - this._log.warn( - {metric}, - 'metric has other than 1 dataPoint' - ); - rendering.push(` ${metric.name} (histogram)`); - } else { - const dp = metric.histogram.dataPoints[0]; - const extras = ['histogram']; - if (metric.unit) { - extras.push(metric.unit); - } - if (dp.attributes) { - extras.push( - `${Object.keys(dp.attributes).length} attrs` - ); + // histogram "${name}" (unit=${unit}) + // ${metricValueRepr} | <-- one for each data point + // ${attrsRepr} | + // -- + // ${metricValueRepr} + // ${attrsRepr} + rendering.push( + `${style('histogram', 'bold')} "${style( + metric.name, + 'magenta' + )}" (unit=${metric.unit})` + ); + for ( + let i = 0; + i < metric.histogram.dataPoints.length; + i++ + ) { + if (i > 0) { + rendering.push(' --'); } + const dp = metric.histogram.dataPoints[i]; + // TODO: consider a meaningful repr of the histogram buckets rendering.push( - ` ${metric.name} (${extras.join( - ', ' - )}): min=${dp.min}, max=${dp.max}` + ` count=${dp.count}, min=${dp.min}, max=${dp.max}` ); + if ( + dp.attributes && + Object.keys(dp.attributes).length > 0 + ) { + let attrSummary = util.inspect(dp.attributes, { + depth: 10, + colors: true, + breakLength: Infinity, + }); + rendering.push(' ' + attrSummary); + } } } else { // TODO handle other metric types better - rendering.push(` ${metric.name} (type=???)`); + rendering.push(`metricType??? "${metric.name}"`); } } } diff --git a/packages/mockotlpserver/lib/styling.js b/packages/mockotlpserver/lib/styling.js new file mode 100644 index 00000000..0aaf5919 --- /dev/null +++ b/packages/mockotlpserver/lib/styling.js @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// This color-related block from Bunyan, with permission. ;) +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +// Suggested colors (some are unreadable in common cases): +// - Good: cyan, yellow (limited use), bold, green, magenta, red +// - Bad: blue (not visible on cmd.exe), grey (same color as background on +// Solarized Dark theme from , see +// issue #160) +var colors = { + bold: [1, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + white: [37, 39], + grey: [90, 39], + black: [30, 39], + blue: [34, 39], + cyan: [36, 39], + green: [32, 39], + magenta: [35, 39], + red: [31, 39], + yellow: [33, 39], +}; +function stylizeWithColor(str, color) { + if (!str) return ''; + var codes = colors[color]; + if (codes) { + return '\x1b[' + codes[0] + 'm' + str + '\x1b[' + codes[1] + 'm'; + } else { + return str; + } +} + +module.exports = { + style: stylizeWithColor, +}; diff --git a/packages/mockotlpserver/lib/waterfall.js b/packages/mockotlpserver/lib/waterfall.js index 814ae2bb..d75ac15b 100644 --- a/packages/mockotlpserver/lib/waterfall.js +++ b/packages/mockotlpserver/lib/waterfall.js @@ -36,6 +36,7 @@ const {Printer} = require('./printers'); const {jsonStringifyTrace} = require('./normalize'); +const {style} = require('./styling'); /* @@ -100,7 +101,9 @@ function renderSpan(span, prefix = '') { gutter = ' '.repeat(6); } - let r = `${gutter} ${prefix}span ${shortId(span.spanId)} "${span.name}"`; + let r = `${gutter} ${prefix}${style('span', 'bold')} ${shortId( + span.spanId + )} "${style(span.name, 'magenta')}"`; const extras = [];