Skip to content

Commit

Permalink
Limit span names/labels to service limits (#345)
Browse files Browse the repository at this point in the history
PR-URL: #345
  • Loading branch information
matthewloring committed Jan 14, 2017
1 parent d31798c commit 94e5dad
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 4 deletions.
12 changes: 11 additions & 1 deletion src/constants.js
Expand Up @@ -24,5 +24,15 @@ module.exports = {
TRACE_AGENT_REQUEST_HEADER: 'x-cloud-trace-agent-request',

/** @const {number} bitmask to determine whether trace is enabled in trace options. */
TRACE_OPTIONS_TRACE_ENABLED: 1 << 0
TRACE_OPTIONS_TRACE_ENABLED: 1 << 0,

/** See: cloud.google.com/trace/api/reference/rest/v1/projects.traces for limits. */
/** Maximum size of a span name in bytes. */
TRACE_SERVICE_SPAN_NAME_LIMIT: 127,

/** Maximum size of a label key in bytes. */
TRACE_SERVICE_LABEL_KEY_LIMIT: 127,

/** Maximum size of a label value in bytes. */
TRACE_SERVICE_LABEL_VALUE_LIMIT: 16 * 1024 - 1,
};
31 changes: 29 additions & 2 deletions src/trace-span.js
Expand Up @@ -17,13 +17,33 @@
'use strict';

var util = require('util');
var constants = require('./constants.js');

/**
* Truncates the provided `string` to be at most `length` bytes
* after utf8 encoding and the appending of '...'.
* We produce the result by iterating over input characters to
* avoid truncating the string potentially producing partial unicode
* characters at the end.
*/
function truncate(string, length) {
string = string.substr(0, length - 3);
while (Buffer.byteLength(string, 'utf8') > length - 3) {
string = string.substr(0, string.length - 1);
}
return string + '...';
}

/**
* Creates a trace span object.
* @constructor
*/
function TraceSpan(name, spanId, parentSpanId) {
this.name = name;
if (Buffer.byteLength(name, 'utf8') > constants.TRACE_SERVICE_SPAN_NAME_LIMIT) {
this.name = truncate(name, constants.TRACE_SERVICE_SPAN_NAME_LIMIT);
} else {
this.name = name;
}
this.parentSpanId = parentSpanId;
this.spanId = spanId;
this.kind = 'RPC_CLIENT';
Expand All @@ -39,7 +59,14 @@ function TraceSpan(name, spanId, parentSpanId) {
* @param {string} value The new value of the label.
*/
TraceSpan.prototype.setLabel = function(key, value) {
this.labels[key] = typeof value === 'object' ? util.inspect(value) : '' + value;
if (Buffer.byteLength(key, 'utf8') > constants.TRACE_SERVICE_LABEL_KEY_LIMIT) {
key = truncate(key, constants.TRACE_SERVICE_LABEL_KEY_LIMIT);
}
var val = typeof value === 'object' ? util.inspect(value) : '' + value;
if (Buffer.byteLength(val, 'utf8') > constants.TRACE_SERVICE_LABEL_VALUE_LIMIT) {
val = truncate(val, constants.TRACE_SERVICE_LABEL_VALUE_LIMIT);
}
this.labels[key] = val;
};


Expand Down
36 changes: 35 additions & 1 deletion test/test-trace-span.js
Expand Up @@ -19,6 +19,7 @@
var assert = require('assert');
var tk = require('timekeeper');
var TraceSpan = require('../src/trace-span.js');
var constants = require('../src/constants.js');


describe('TraceSpan', function() {
Expand All @@ -45,12 +46,45 @@ describe('TraceSpan', function() {
assert.equal(span.labels.c, '5');
});

it ('serializes object labels correctly', function() {
it('serializes object labels correctly', function() {
var span = new TraceSpan('name', 1, 0);
span.setLabel('a', [{i: 5}, {j: 6}]);
assert.equal(span.labels.a, '[ { i: 5 }, { j: 6 } ]');
});

it('handles unicode characters correctly when truncating', function() {
var longName = Array(120).join('☃');
var span = new TraceSpan(longName, 1, 0);
assert.equal(
span.name,
Array(42).join('☃') + '...');
});

it('truncate large span names to limit', function() {
var longName = Array(200).join('a');
var span = new TraceSpan(longName, 1, 0);
assert.equal(
span.name,
Array(constants.TRACE_SERVICE_SPAN_NAME_LIMIT - 2).join('a') + '...');
});

it('truncate large label keys to limit', function() {
var span = new TraceSpan('name', 1, 0);
var longLabelKey = Array(200).join('a');
span.setLabel(longLabelKey, 5);
assert.equal(
span.labels[Array(constants.TRACE_SERVICE_LABEL_KEY_LIMIT - 2).join('a') + '...'],
5);
});

it('truncate large label values to limit', function() {
var span = new TraceSpan('name', 1, 0);
var longLabelVal = Array(16550).join('a');
span.setLabel('a', longLabelVal);
assert.equal(span.labels.a,
Array(constants.TRACE_SERVICE_LABEL_VALUE_LIMIT - 2).join('a') + '...');
});

it('closes', function() {
var span = new TraceSpan('name', 1, 0);
assert.equal(span.endTime, '');
Expand Down

0 comments on commit 94e5dad

Please sign in to comment.