Skip to content

Commit

Permalink
Remove access of span.attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
changliu-wk committed Apr 1, 2022
1 parent e8aad10 commit d06c0e2
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 155 deletions.
38 changes: 26 additions & 12 deletions lib/src/api/common/attribute.dart
Original file line number Diff line number Diff line change
@@ -1,34 +1,48 @@
import 'package:opentelemetry/src/sdk/internal/utils.dart';

/// A representation of a single piece of metadata attached to trace span.
class Attribute {
final String key;
final Object value;

/// Create an Attribute from a String value.
Attribute.fromString(this.key, String this.value);
Attribute.fromString(this.key, String this.value) {
Utils.checkArgument(key != null, "key can't be null");
}

/// Create an Attribute from a boolean value.
// ignore: avoid_positional_boolean_parameters
Attribute.fromBoolean(this.key, bool this.value);
Attribute.fromBoolean(this.key, bool this.value) {
Utils.checkArgument(key != null, "key can't be null");
}

/// Create an Attribute from a double-precision floating-point value.
Attribute.fromDouble(this.key, double this.value);
Attribute.fromDouble(this.key, double this.value) {
Utils.checkArgument(key != null, "key can't be null");
}

/// Create an Attribute from an integer value.
Attribute.fromInt(this.key, int this.value);
Attribute.fromInt(this.key, int this.value) {
Utils.checkArgument(key != null, "key can't be null");
}

/// Create an Attribute from a list of String values.
Attribute.fromStringList(this.key, List<String> this.value);
Attribute.fromStringList(this.key, List<String> this.value) {
Utils.checkArgument(key != null, "key can't be null");
}

/// Create an Attribute from a list of boolean values.
Attribute.fromBooleanList(this.key, List<bool> this.value);
Attribute.fromBooleanList(this.key, List<bool> this.value) {
Utils.checkArgument(key != null, "key can't be null");
}

/// Create an Attribute from a list of double-precision floating-point values.
Attribute.fromDoubleList(this.key, List<double> this.value);
Attribute.fromDoubleList(this.key, List<double> this.value) {
Utils.checkArgument(key != null, "key can't be null");
}

/// Create an Attribute from a list of integer values.
Attribute.fromIntList(this.key, List<int> this.value);

///Create an Attribute from an object.
///Do we need to do a type check of value?
Attribute.fromObject(this.key, this.value);
Attribute.fromIntList(this.key, List<int> this.value) {
Utils.checkArgument(key != null, "key can't be null");
}
}
18 changes: 0 additions & 18 deletions lib/src/api/common/attribute_util.dart

This file was deleted.

28 changes: 5 additions & 23 deletions lib/src/api/common/attributes.dart
Original file line number Diff line number Diff line change
@@ -1,45 +1,27 @@
import 'attribute.dart';
import 'attribute_util.dart';

/// A representation of a collection of metadata attached to a trace span.
/// From OpenTelemetry Specification about attributes,
/// https://opentelemetry.io/docs/reference/specification/common/common/#exempt-entities
/// Some attributes are exempt from limits, in this case, it is set as -1.
/// If it is 0, it is considered as not accepting attributes.
class Attributes {
Map<String, Object> _attributes = {};
int _maxNumAttributes;
int _maxNumAttributesLength;

/// Instantiate an empty Attributes.
Attributes.empty([int maxNumAttributes, int maxNumAttributesLength]) {
Attributes.empty() {
_attributes = {};
_maxNumAttributes = maxNumAttributes ?? -1; // no restrain limits
_maxNumAttributesLength = maxNumAttributesLength ?? -1;
}

/// Retrieve the value associated with the Attribute with key [key].
Object get(String key) => _attributes[key];

///
int get length => _attributes.length;

/// Retrieve the keys of all Attributes in this collection.
Iterable<String> get keys => _attributes.keys;

///Retrieve the number of attributes contained in this.
int get size => _attributes.length;

/// Add an Attribute [attribute].
/// If an Attribute with the same key already exists, it will be overwritten.
/// If the number of attributes is too many, it will drop it silently.
/// If the attribute value length is too long, it will be truncated.
void add(Attribute attribute) {
if (_maxNumAttributes == -1) {
_attributes[attribute.key] = attribute.value;
return;
}
if (_attributes.length >= _maxNumAttributes &&
!_attributes.containsKey(attribute.key)) return;
_attributes[attribute.key] = AttributeUtil.applyAttributeLengthLimit(
attribute.value, _maxNumAttributesLength);
_attributes[attribute.key] = attribute.value;
}

/// Add all Attributes in List [attributes].
Expand Down
3 changes: 1 addition & 2 deletions lib/src/api/trace/nonrecording_span.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ class NonRecordingSpan implements api.Span {

NonRecordingSpan(this._spanContext);

@override
api.Attributes get attributes => _attributes;

@override
set attributes(api.Attributes attributes) {
void setAttributes(api.Attributes attributes) {
return;
}

Expand Down
5 changes: 1 addition & 4 deletions lib/src/api/trace/span.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ abstract class Span {
api.SpanStatus get status;

/// Set metadata to be included on this span.
set attributes(api.Attributes attributes);

/// Retrieve metadata included on this span.
api.Attributes get attributes;
void setAttributes(api.Attributes attributes);

/// Retrieve the resource on this span.
api.Resource get resource;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/sdk/internal/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ class Utils {
///Check argument
// ignore: avoid_positional_boolean_parameters
static void checkArgument(bool isValid, String errorMessage) {
if (!isValid) throw Exception(errorMessage);
if (!isValid) throw ArgumentError(errorMessage);
}
}
3 changes: 2 additions & 1 deletion lib/src/sdk/trace/exporters/collector_exporter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'opentelemetry/proto/collector/trace/v1/trace_service.pb.dart'
import 'opentelemetry/proto/trace/v1/trace.pb.dart' as pb_trace;
import 'opentelemetry/proto/resource/v1/resource.pb.dart' as pb_resource;
import 'opentelemetry/proto/common/v1/common.pb.dart' as pb_common;
import '../span.dart' as spansdk;

class CollectorExporter implements api.SpanExporter {
Uri uri;
Expand Down Expand Up @@ -74,7 +75,7 @@ class CollectorExporter implements api.SpanExporter {
return rss;
}

pb_trace.Span _spanToProtobuf(api.Span span) {
pb_trace.Span _spanToProtobuf(spansdk.Span span) {
pb_trace.Status_StatusCode statusCode;
switch (span.status.code) {
case api.StatusCode.unset:
Expand Down
101 changes: 62 additions & 39 deletions lib/src/sdk/trace/span.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:fixnum/fixnum.dart';
import 'package:opentelemetry/src/sdk/trace/span_limits.dart';

import '../../../api.dart' as api;
import '../../../api.dart';

/// A representation of a single operation within a trace.
class Span implements api.Span {
Expand All @@ -25,14 +26,13 @@ class Span implements api.Span {
/// Construct a [Span].
Span(this.name, this._spanContext, this._parentSpanId, this._processors,
this._resource, this._instrumentationLibrary,
{api.Attributes attributes, SpanLimits limits}) {
{api.Attributes attributes, SpanLimits spanlimits}) {
_startTime = Int64(DateTime.now().toUtc().microsecondsSinceEpoch);

if (limits != null) _spanLimits = limits;
_attributes = api.Attributes.empty(
_spanLimits.maxNumAttributes, _spanLimits.maxNumAttributeLength);
if (spanlimits != null) _spanLimits = spanlimits;
_attributes = Attributes.empty();
if (attributes != null) {
_setAttributes(attributes);
setAttributes(attributes);
}

for (var i = 0; i < _processors.length; i++) {
Expand Down Expand Up @@ -86,59 +86,82 @@ class Span implements api.Span {
api.InstrumentationLibrary get instrumentationLibrary =>
_instrumentationLibrary;

@override
/// Retrieve metadata included on this span.
api.Attributes get attributes => _attributes;

///not sure about this part, if span.attributes = attributes, then we need to
///discard all previous added attributes,create a new one?
@override
set attributes(api.Attributes attributes) {
_setAttributes(attributes);
}
void setAttributes(api.Attributes attributes) {
if (_spanLimits.maxNumAttributes == 0) return;

void _setAttributes(api.Attributes attributes) {
for (final key in attributes.keys) {
final val = attributes.get(key);

//final reBuild = _reBuildAttribute(key, val);
//we also could do this if we add an API in attribute.dart
final reBuild = api.Attribute.fromObject(key, val);
final obj = _attributes.get(key);
//If current attributes.length is equal or greater than maxNumAttributes and
//key is not in current map, drop it.
if (_attributes.length >= _spanLimits.maxNumAttributes && obj == null) {
continue;
}

//otherwise rebuild this attribute, truncate it and put it in
final reBuild = _reBuildAttribute(key, attributes.get(key));
_attributes.add(reBuild);
}
}

/// reBuild an attribute, this way it is tightly coupled with the type we supported,
/// if later we added more types, then we need to change this method.
// api.Attribute _reBuildAttribute(String key, dynamic value) {
// if (value is bool) {
// return api.Attribute.fromBoolean(key, value);
// } else if (value is List<bool>) {
// return api.Attribute.fromBooleanList(key, value);
// } else if (value is int) {
// return api.Attribute.fromInt(key, value);
// } else if (value is List<int>) {
// return api.Attribute.fromIntList(key, value);
// } else if (value is double) {
// return api.Attribute.fromDouble(key, value);
// } else if (value is List<double>) {
// return api.Attribute.fromDoubleList(key, value);
// } else if (value is String) {
// return api.Attribute.fromString(key, value);
// } else if (value is List<String>) {
// return api.Attribute.fromStringList(key, value);
// } else {
// throw Exception("No responding type with this attribute's value");
// }
// }
api.Attribute _reBuildAttribute(String key, dynamic value) {
if (value is bool) {
return api.Attribute.fromBoolean(key, value);
} else if (value is List<bool>) {
return api.Attribute.fromBooleanList(key, value);
} else if (value is int) {
return api.Attribute.fromInt(key, value);
} else if (value is List<int>) {
return api.Attribute.fromIntList(key, value);
} else if (value is double) {
return api.Attribute.fromDouble(key, value);
} else if (value is List<double>) {
return api.Attribute.fromDoubleList(key, value);
} else if (value is String) {
return api.Attribute.fromString(key,
_applyAttributeLengthLimit(value, _spanLimits.maxNumAttributeLength));
} else if (value is List<String>) {
for (var i = 0; i < value.length; i++) {
value[i] = _applyAttributeLengthLimit(
value[i], _spanLimits.maxNumAttributeLength);
}
return api.Attribute.fromStringList(key, value);
} else {
throw Exception("No responding type with this attribute's value");
}
}

@override
void recordException(dynamic exception, {StackTrace stackTrace}) {
// ignore: todo
// TODO: O11Y-1531: Consider integration of Events here.
setStatus(api.StatusCode.error, description: exception.toString());
attributes.addAll([
_attributes.addAll([
api.Attribute.fromBoolean('error', true),
api.Attribute.fromString('exception', exception.toString()),
api.Attribute.fromString('stacktrace', stackTrace.toString()),
]);
}

//Truncate just strings which length is longer than configuration.
//Reference: https://github.com/open-telemetry/opentelemetry-java/blob/14ffacd1cdd22f5aa556eeda4a569c7f144eadf2/sdk/common/src/main/java/io/opentelemetry/sdk/internal/AttributeUtil.java#L80
static Object _applyAttributeLengthLimit(Object value, int lengthLimit) {
if (value is String) {
return value.length > lengthLimit
? value.substring(0, lengthLimit)
: value;
} else if (value is List<String>) {
for (var i = 0; i < value.length; i++) {
value[i] = value[i].length > lengthLimit
? value[i].substring(0, lengthLimit)
: value[i];
}
}
return value;
}
}
26 changes: 13 additions & 13 deletions lib/src/sdk/trace/span_limits.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import '../internal/utils.dart';

class SpanLimits {
final DEFAULT_MAXNUM_ATTRIBUTES = 200;
final DEFAULT_MAXNUM_EVENTS = 128;
final DEFAULT_MAXNUM_LINKS = 128;
final DEFAULT_MAXNUM_ATTRIBUTE_PER_EVENT = 128;
final DEFAULT_MAXNUM_ATTRIBUTES_PER_LINK = 128;
final DEFAULT_MAXNUM_ATTRIBUTES_LENGTH = 1000;
final _DEFAULT_MAXNUM_ATTRIBUTES = 200;
final _DEFAULT_MAXNUM_EVENTS = 128;
final _DEFAULT_MAXNUM_LINKS = 128;
final _DEFAULT_MAXNUM_ATTRIBUTE_PER_EVENT = 128;
final _DEFAULT_MAXNUM_ATTRIBUTES_PER_LINK = 128;
final _DEFAULT_MAXNUM_ATTRIBUTES_LENGTH = 1000;

int _maxNumAttributes;
int _maxNumEvents;
Expand All @@ -15,7 +15,7 @@ class SpanLimits {
int _maxNumAttributesPerLink;
int _maxNumAttributeLength;

///
///setters
set maxNumAttributes(int maxNumberOfAttributes) {
Utils.checkArgument(maxNumberOfAttributes >= 0,
'maxNumberOfAttributes must be greater or equal to zero');
Expand Down Expand Up @@ -70,14 +70,14 @@ class SpanLimits {
int maxNumAttributesPerEvent,
int maxNumAttributesPerLink,
int maxNumAttributeLength}) {
_maxNumAttributes = maxNumAttributes ?? DEFAULT_MAXNUM_ATTRIBUTES;
_maxNumEvents = maxNumEvents ?? DEFAULT_MAXNUM_EVENTS;
_maxNumLink = maxNumLink ?? DEFAULT_MAXNUM_LINKS;
_maxNumAttributes = maxNumAttributes ?? _DEFAULT_MAXNUM_ATTRIBUTES;
_maxNumEvents = maxNumEvents ?? _DEFAULT_MAXNUM_EVENTS;
_maxNumLink = maxNumLink ?? _DEFAULT_MAXNUM_LINKS;
_maxNumAttributesPerEvent =
maxNumAttributesPerEvent ?? DEFAULT_MAXNUM_ATTRIBUTE_PER_EVENT;
maxNumAttributesPerEvent ?? _DEFAULT_MAXNUM_ATTRIBUTE_PER_EVENT;
_maxNumAttributesPerLink =
maxNumAttributesPerLink ?? DEFAULT_MAXNUM_ATTRIBUTES_PER_LINK;
maxNumAttributesPerLink ?? _DEFAULT_MAXNUM_ATTRIBUTES_PER_LINK;
_maxNumAttributeLength =
maxNumAttributeLength ?? DEFAULT_MAXNUM_ATTRIBUTES_LENGTH;
maxNumAttributeLength ?? _DEFAULT_MAXNUM_ATTRIBUTES_LENGTH;
}
}
5 changes: 2 additions & 3 deletions lib/src/sdk/trace/tracer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ class Tracer implements api.Tracer {
api.Span startSpan(String name,
{api.Context context, api.Attributes attributes}) {
context ??= api.Context.current;
attributes ??= api.Attributes.empty(
_spanLimits.maxNumAttributes, _spanLimits.maxNumAttributeLength);
attributes ??= api.Attributes.empty();

// If a valid, active Span is present in the context, use it as this Span's
// parent. If the Context does not contain an active parent Span, create
Expand Down Expand Up @@ -56,7 +55,7 @@ class Tracer implements api.Tracer {

return sdk.Span(name, spanContext, parentSpanId, _processors, _resource,
_instrumentationLibrary,
attributes: attributes, limits: _spanLimits);
attributes: attributes, spanlimits: _spanLimits);
}

/// Records a span of the given [name] for the given function
Expand Down
Loading

0 comments on commit d06c0e2

Please sign in to comment.