Skip to content

v0.3.0

Latest
Compare
Choose a tag to compare
@maraisr maraisr released this 19 Mar 05:59
· 69 commits to main since this release
3c0dd72

Features

🎉 rian/async

This is the reason you would want to update. Now that Cloudflare Workers is on its way to supporting async_hooks, and with existing node support. It just made sense to expose a new, more ergonomic way to source parent spans.

Simply use the new rian/async module as opposed to rian, should largely be a drop in replacement for rian.

rian -> rian/async drop in example

Once the breaking changes below has been implemented:

- import { tracer } from 'rian';
+ import { tracer, span } from 'rian/async';

const trace = tracer('name');

// ...

- trace.span('GET /')( ... );
+ trace(() => {
+     span('GET /')( ... );
+ });

any time you had a scope.span that stays unchanged. But as long as the right execution topology is present you can replace it with:

- const newScope = scope.span('name');
+ const newScope = span('name');

The idea here is that span's can can be captured in any function, without needing to pass the scope through all your methods.

import { configure, tracer, span, currentSpan, report } from 'rian/async';
import { exporter } from 'rian/exporter.otel.http';

function handler(req) {
  return span(`${req.method} ${req.path}`)(async () => {
    const s = currentSpan();
    s.set_context({ user_id: req.params.user_id });

    const data = await s.span('db::read')(() => db_execute('SELECT * FROM users'));

    const processing_span = s.span('process records');

    for (let row of data) {
      processing_span.add_event('doing stuff', { id: row.id });
      do_stuff(row);
    }

    processing_span.end();

    return reply(200, { data });
  });
}

const httpTrace = tracer('http');

http.listen((req, executionCtx) => {
  executionCtx.defer(() => report(exporter));
  return httpTrace(() => handler(req));
});

BREAKING

  1. create has been renamed to tracer and no longer creates a root span. see dbb9ab5, 73a688b

    - const scope = create('GET /');
    + const scope = tracer('name').span('GET /');
  2. scope.end on the root no longer calls the exporter, use rian.report instead. see dbb9ab5

    import { report } from 'rian';
    - const scope = create('name', { exporter });
    - scope.end();
    + report(exporter);
  3. fork has been renamed to span. see see 73a688b

    - scope.fork('name');
    + scope.span('name');
  4. samplers now get given the new span's id, and will influence the sample flag of the traceparent. see 724248d

  5. new configure method to configure the runtime context. Previously this was the context property on create. see 0c53eeb

    - create('name', {
    -     context: {
    -         'service.name': 'my-service',
    -         'service.version': '1.2.3',
    -     }
    - });
    
    + configure('my-service', { 'service.version': '1.2.3' });

    This should only be ran once in the runtime. service.name is set for you in doing this.

  6. measure no longer receives a name argument. Meaning the scope should be pre-started. see 0cdd3ac

    - const data = await measure(scope, 'name', get_data);
    + const data = await measure(scope.span('name'), get_data);
  7. wrap is removed see 0cdd3ac

    But you can build your own:

    const wrap = (name: string, fn: Function) = (scope: Scope, ...args) => scope.span('name')(fn(...args));
    
    const get_data_wrapped = wrap(get_data);
    
    get_data_wrapped(scope, arg1, arg2);

    with the new rian/async the semantics on how a scope is sourced changes, which means you could simplify:

    import { span } from 'rian/async';
    const wrap = (name: string, fn: Function) => (...args) => span(name)(fn(args));
  8. exporter.otel.http now ships otl v0.9

Full Changelog: v0.2.5...v0.3.0