Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial branch #1

Merged
merged 2 commits into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
# @Workiva/product-new-relic will be requested for
# review when someone opens a pull request.
* @Workiva/product-new-relic
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FROM scratch
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
# opentelemetry-dart
# OpenTelemetry for Dart

This repo is intended to be the Dart implementation of the OpenTelemetry project, with a
long-term goal of being open sourced.

All contributions and designs should follow the
[OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification)
in an effort to be consistent with [all other languages](https://github.com/open-telemetry).
Empty file.
12 changes: 12 additions & 0 deletions packages/opentelemetry_api/lib/opentelemetry_api.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export 'src/context.dart'
show
isInstrumentationSuppressed,
suppressInstrumentationKey,
unsuppressInstrumentation;
export 'src/trace/span_context.dart';
export 'src/trace/span_kind.dart';
export 'src/trace/span.dart';
export 'src/trace/status.dart';
export 'src/trace/trace_state.dart';
export 'src/trace/tracer_provider.dart';
export 'src/trace/tracer.dart';
12 changes: 12 additions & 0 deletions packages/opentelemetry_api/lib/src/context.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'package:opentelemetry_context/opentelemetry_context.dart';

final suppressInstrumentationKey = Context.createKey('OpenTelemetry suppress instrumentation');

Context suppressInstrumentation(Context context) =>
context.setValue(suppressInstrumentationKey, true);

Context unsuppressInstrumentation(Context context) =>
context.setValue(suppressInstrumentationKey, false);

bool isInstrumentationSuppressed(Context context) =>
context.getValue(suppressInstrumentationKey) ?? false;
47 changes: 47 additions & 0 deletions packages/opentelemetry_api/lib/src/trace/noop_span.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

import 'package:opentelemetry_api/src/trace/span_context.dart';

import 'package:opentelemetry_api/src/trace/status.dart';

import 'span.dart';

class NoopSpan implements Span {
@override
void addEvent(String name, {Map<String, Object> attributes, DateTime startTime}) {
// TODO: implement addEvent
}

@override
// TODO: implement context
SpanContext get context => null;

@override
void end({DateTime endTime}) {
// TODO: implement end
}

@override
// TODO: implement isRecording
bool get isRecording => null;

@override
void setAllAttributes(Map<String, Object> attributes) {
// TODO: implement setAllAttributes
}

@override
void setAttribute(String key, Object value) {
// TODO: implement setAttribute
}

@override
void setStatus(StatusCode code, {String description}) {
// TODO: implement setStatus
}

@override
void updateName(String name) {
// TODO: implement updateName
}

}
69 changes: 69 additions & 0 deletions packages/opentelemetry_api/lib/src/trace/span.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import 'span_context.dart';
import 'status.dart';

/// A representation of a single operation within a trace.
///
/// Examples of a span might include remote procedure calls or in-process
/// function calls to sub-components. A trace has a single, top-level "root"
/// span that in turn may haze zero or more child Spans, which in turn may have
/// children.
///
/// Spans are created by [Tracer.startSpan].
abstract class Span {
/// The context associated with this span.
///
/// This context is an immutable, serializable identifier for this span that
/// can be used to create new child spans and remains usable even after this
/// span ends.
SpanContext get context;

/// Whether this span is active and recording information like events via
/// [addEvent], attributes via [setAttributes], and so on.
bool get isRecording;

/// Adds an event to this span.
///
/// If [attributes] and/or [startTime] are given, they will be set as
/// attributes to this span.
///
/// Values in [attributes] must be of type [String], [num], [boolean], or a
/// [List] of these types. Null or improperly typed values will result in
/// undefined behavior.
void addEvent(String name, {Map<String, Object> attributes, DateTime startTime});

/// Marks the end of this span's execution.
///
/// [endTime] will be set as this span's end time. If not provided, the
/// current time will be used.
void end({DateTime endTime});

// void recordException(Object error, {Map<String, Object> attributes, StackTrace stackTrace, DateTime startTime});

/// Sets an attribute to this span.
///
/// [value] must non-null and of type [String], [num], [boolean], or a [List]
/// of one of these types. Null or improperly typed values will result in
/// undefined behavior.
void setAttribute(String key, Object value);

/// Sets multiple attributes to this span.
///
/// Values in [attributes] must be of type [String], [num], [boolean], or a
/// [List] of these types. Null or improperly typed values will result in
/// undefined behavior.
void setAllAttributes(Map<String, Object> attributes);

/// Sets this span's status.
///
/// If used, this will override the default status of [StatusCode.unset] and
/// will also override the value of previous calls on this Span.
void setStatus(StatusCode code, {String description});

/// Updates this span's name.
///
/// Upon this update, any sampling behavior based on span name will depend on
/// the implementation.
void updateName(String name) {

}
}
23 changes: 23 additions & 0 deletions packages/opentelemetry_api/lib/src/trace/span_context.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'package:meta/meta.dart';

import 'trace_state.dart';

class SpanContext {
static SpanContext create(String traceId, String spanId, num traceFlags, TraceState traceState)
=> SpanContext._(traceId, spanId, traceFlags, traceState, isRemote: false);

static SpanContext createFromRemoteParent(String traceId, String spanId, num traceFlags, TraceState traceState)
=> SpanContext._(traceId, spanId, traceFlags, traceState, isRemote: true);

final bool isRemote;

final String spanId;

final num traceFlags;

final String traceId;

final TraceState traceState;

SpanContext._(this.traceId, this.spanId, this.traceFlags, this.traceState, {@required this.isRemote})
}
7 changes: 7 additions & 0 deletions packages/opentelemetry_api/lib/src/trace/span_kind.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
enum SpanKind {
client,
server,
producer,
consumer,
internal,
}
11 changes: 11 additions & 0 deletions packages/opentelemetry_api/lib/src/trace/status.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
abstract class Status {
StatusCode get code;

String get message;
}

enum StatusCode {
ok,
unset,
error,
}
9 changes: 9 additions & 0 deletions packages/opentelemetry_api/lib/src/trace/trace_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
abstract class TraceState {
TraceState get(String key);

TraceState set(String key, String value);

TraceState unset(String key);

String serialize();
}
36 changes: 36 additions & 0 deletions packages/opentelemetry_api/lib/src/trace/tracer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:opentelemetry_context/opentelemetry_context.dart';

import 'span.dart';
import 'span_kind.dart';

/// An interface for creating [Span]s and propagating context in-process.
///
/// Users may choose to use manual or automatic Context propagation. Because of
/// that, this class offers APIs to facilitate both usages.
abstract class Tracer {
/// Returns the current Span from the current context if available.
///
/// If there is no Span associated with the current context, this returns
/// `null`.
///
/// To install a [Span] to the current Context, use [Tracer.withSpan].
// Span getCurrentSpan();

/// Starts a new [Span] without setting it as the current span in this
/// tracer's context.
///
/// This method does NOT modify the current Context. To install a [Span] to
/// the current Context use [Tracer.withSpan].
Span startSpan(String name, {Context context, SpanKind kind, DateTime startTime});

/// Calls [fn] within the Context provided by [span].
///
/// This is a convenience method for creating spans attached to the tracer's
/// context. Applications that need more control over the span lifetime should
/// use [Tracer.startSpan].
// T withSpan<T>(Span span, T Function() fn);

/// Binds the given [context] span to [target], or propagates the current
/// context if one is not given.
// T bind<T>(T target, {Span context});
}
11 changes: 11 additions & 0 deletions packages/opentelemetry_api/lib/src/trace/tracer_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'tracer.dart';

/// A registry for creating named [Tracer]s.
abstract class TracerProvider {
/// Returns a Tracer, creating one if one with the given [name] and [version]
/// is not already created.
///
/// [name] should be the name of the tracer or instrumentation library.
/// [version] should be the version of the tracer or instrumentation library.
Tracer getTracer(String name, {String version});
}
12 changes: 12 additions & 0 deletions packages/opentelemetry_api/lib/src/trace/utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'span_context.dart';

const invalidSpanId = '0000000000000000';
const invalidTraceId = '00000000000000000000000000000000';
const invalidSpanContext = SpanContext.create(
invalidTraceId,
invalidSpanId,
traceFlags: TraceFlags.NONE);

class TraceFlags {
static const num none = 0x0;
}
12 changes: 12 additions & 0 deletions packages/opentelemetry_api/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: opentelemetry_api
version: 0.0.0
publish_to: none

dependencies:
logging: ^0.11.4
meta: ^1.2.4
opentelemetry_context: ^0.0.0

dependency_overrides:
opentelemetry_context:
path: ../opentelemetry_context
Empty file.
106 changes: 106 additions & 0 deletions packages/opentelemetry_context/lib/opentelemetry_context.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/// This library provides functions for interacting with the active "Context"
/// for the purposes of propagating execution-scoped values across API
/// boundaries and between logically associated execution units.
///
/// The OpenTelemetry SDKs require a mechanism for propagating context and the
/// OpenTelemetry specification outlines the requirements for this context
/// implementation: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/context/context.md
///
/// The spec notes that "languages are expected to use the single, widely used
/// Context implementation if one exists for them." Fortunately, the Dart SDK
/// provides just that with [Zone] - a representation of "an environment that
/// remains stable across asynchronous calls." [Zone] also meets the core
/// requirements of immutability and being able to read and write values:
///
/// - Immutable: a Zone's values are set when the Zone is created and cannot be
/// changed aftewards.
/// - Reading and writing values: a Zone implements the `[]` operator, allowing
/// values to be read directly from it like a [Map], and writing values is
/// possible only by forking another Zone and providing values to add/override
/// (the rest of the values will be inherited from the forked Zone).
///
/// This library provides a simple abstraction over [Zone] for the purpose of
/// implementing the rest of the Context specification. OpenTelemetry SDKs and
/// instrumentation libraries should use this [Context] API instead of a [Zone]
/// directly. Other users should usually not interact with Context at all and
/// should instead manipulate it through cross-cutting concerns APIs provided by
/// OpenTelemetry SDKs.
library opentelemetry_context;

import 'dart:async';

class Context {
/// The active context.
static Context get current => _current ?? Context._(Zone.current);
static Context _current;

/// Returns a key to be used to read and/or write values to a context.
///
/// [name] is for debug purposes only and does not uniquely identify the key.
/// Multiple calls to this function with the same [name] will not return
/// identical keys.
static ContextKey createKey(String name) => ContextKey(name);

/// Makes [context] the active context (such that [current] returns this given
/// context) and returns a scope that should closed by passing it to [detach].
///
/// Every call to [attach] should result in a corresponding call to [detach].
static Scope attach(Context context) {
if (context == null) {
// Null context not allowed, so ignore it.
return Scope._noop;
}

if (context._zone == _current?._zone) {
return Scope._noop;
}

var prev = _current;
_current = context;
return Scope._(() {
if (_current._zone != context._zone) {
// TODO: log
}
_current = prev;
});
}

/// Resets the active context to the value that was active before attaching
/// the context associated with [scope].
///
/// If [scope] is associated with a context that is not the active one, an
/// error will be logged.
void detach(Scope scope) {
scope._close();
}

/// The implicit "context" that is used to implement the APIs on this class.
final Zone _zone;

Context._(this._zone);

/// Returns the value from this context identified by [key], or null if no
/// such value is set.
T getValue<T>(ContextKey key) => _zone[key];

/// Returns a new context created from this one with the given key/value pair
/// set.
///
/// If [key] was already set in this context, it will be overridden. The rest
/// of the context values will be inherited.
Context setValue(ContextKey key, Object value) => Context._(_zone.fork(zoneValues: {key: value}));
}

class ContextKey {
final String name;
ContextKey(this.name);

@override
String toString() => 'ContextKey: $name';
}

class Scope {
static Scope _noop = Scope._(() {});
void Function() _close;
Scope._(this._close);
}
Loading