SDKs
JS/TS SDK
TypeScript SDK - Advanced Configuration
17 min
masking to prevent sensitive data from being sent to abv, you can provide a mask function to the abvspanprocessor this function will be applied to the input , output , and metadata of every observation the function receives an object { data } , where data is the stringified json of the attribute's value it should return the masked data instrumentation ts import { nodesdk } from "@opentelemetry/sdk node"; import { abvspanprocessor } from "@abvdev/otel"; const spanprocessor = new abvspanprocessor({ mask ({ data }) => { // a simple regex to mask credit card numbers const maskeddata = data replace( /\b\d{4}\[ ]?\d{4}\[ ]?\d{4}\[ ]?\d{4}\b/g, " masked credit card " ); return maskeddata; }, }); const sdk = new nodesdk({ spanprocessors \[spanprocessor], }); sdk start(); filtering spans you can provide a predicate function shouldexportspan to the abvspanprocessor to decide on a per span basis whether it should be exported to abv filtering spans may break the parent child relationships in your traces for example, if you filter out a parent span but keep its children, you may see “orphaned” observations in the abv ui consider the impact on trace structure when configuring shouldexportspan instrumentation ts import { nodesdk } from "@opentelemetry/sdk node"; import { abvspanprocessor, shouldexportspan } from "@abvdev/otel"; // example filter out all spans from the 'express' instrumentation const shouldexportspan shouldexportspan = ({ otelspan }) => otelspan instrumentationscope name !== "express"; const sdk = new nodesdk({ spanprocessors \[new abvspanprocessor({ shouldexportspan })], }); sdk start(); if you want to include only llm observability related spans, you can configure an allowlist like so instrumentation ts import { shouldexportspan } from "@abvdev/otel"; const shouldexportspan shouldexportspan = ({ otelspan }) => \["abv sdk", "ai"] includes(otelspan instrumentationscope name); if you would like to exclude abv spans from being sent to third party observability backends configured in your opentelemetry setup, see typescript sdk advanced configuration /#isolated tracer provider sampling abv respects opentelemetry's sampling decisions you can configure a sampler in your otel sdk to control which traces are sent to abv this is useful for managing costs and reducing noise in high volume applications here is an example of how to configure a traceidratiobasedsampler to send only 20% of traces instrumentation ts import { nodesdk } from "@opentelemetry/sdk node"; import { abvspanprocessor } from "@abvdev/otel"; import { traceidratiobasedsampler } from "@opentelemetry/sdk trace base"; const sdk = new nodesdk({ // sample 20% of all traces sampler new traceidratiobasedsampler(0 2), spanprocessors \[new abvspanprocessor()], }); sdk start(); for more advanced sampling strategies, refer to the opentelemetry js sampling documentation managing trace and observation ids in abv, every trace and observation has a unique identifier understanding their format and how to set them is useful for integrating with other systems trace ids are 32 character lowercase hexadecimal strings, representing 16 bytes of data observation ids (also known as span ids in opentelemetry) are 16 character lowercase hexadecimal strings, representing 8 bytes while the sdk handles id generation automatically, you may manually set them to align with external systems or create specific trace structures this is done using the parentspancontext option in tracing methods when starting a new trace by setting a traceid , you must also provide an arbitrary parent spanid for the parent observation the parent span id value is irrelevant as long as it is a valid 16 hexchar string as the span does not actually exist but is only used for trace id inheritance of the created observation you can create valid, deterministic trace ids from a seed string using createtraceid this is useful for correlating abv traces with ids from external systems, like a support ticket id import { createtraceid, startobservation } from "@abvdev/tracing"; const externalid = "support ticket 54321"; // generate a valid, deterministic traceid from the external id const abvtraceid = await createtraceid(externalid); // you can now start a new trace with this id const rootspan = startobservation( "process ticket", {}, { parentspancontext { traceid abvtraceid, spanid "0123456789abcdef", // a valid 16 hexchar string; value is irrelevant as parent span does not exist but only used for inheritance traceflags 1, // mark trace as sampled }, } ); // later, you can regenerate the same traceid to score or retrieve the trace const scoringtraceid = await createtraceid(externalid); // scoringtraceid will be the same as abvtraceid you may also access the current active trace id via the getactivetraceid function import { startobservation, getactivetraceid } from "@abvdev/tracing"; await startobservation("run", async (span) => { const traceid = getactivetraceid(); console log(`current trace id ${traceid}`); }); logging you can configure the global sdk logger to control the verbosity of log output this is useful for debugging in code import { configuregloballogger, loglevel } from "@abvdev/core"; // set the log level to debug to see all log messages configuregloballogger({ level loglevel debug }); available log levels are debug , info , warn , and error via environment variable you can also set the log level using the abv log level environment variable export abv log level="debug" serverless environments in short lived environments such as serverless functions (e g , vercel functions, aws lambda), you must explicitly flush the traces before the process exits or the runtime environment is frozen generic serverless function export the processor from your otel sdk setup file in order to flush it later instrumentation ts import { nodesdk } from "@opentelemetry/sdk node"; import { abvspanprocessor } from "@abvdev/otel"; // export the processor to be able to flush it export const abvspanprocessor = new abvspanprocessor(); const sdk = new nodesdk({ spanprocessors \[abvspanprocessor], }); sdk start(); in your serverless function handler, call forceflush() on the span processor before the function exits handler ts import { abvspanprocessor } from " /instrumentation"; export async function handler(event, context) { // your application logic // flush before exiting await abvspanprocessor forceflush(); } vercel cloud functions export the processor from your instrumentation ts file in order to flush it later instrumentation ts import { nodesdk } from "@opentelemetry/sdk node"; import { abvspanprocessor } from "@abvdev/otel"; // export the processor to be able to flush it export const abvspanprocessor = new abvspanprocessor(); const sdk = new nodesdk({ spanprocessors \[abvspanprocessor], }); sdk start(); in vercel cloud functions, please use the after utility to schedule a flush after the request has completed route ts import { after } from "next/server"; import { abvspanprocessor } from " /instrumentation ts"; export async function post() { // existing request logic // schedule flush after request has completed after(async () => { await abvspanprocessor forceflush(); }); // send response } isolated tracer provider the abv js sdk uses the global opentelemetry tracerprovider to attach its span processor and create tracers that emit spans this means that if you have an existing opentelemetry setup with another destination configured for your spans (e g , datadog), you will see abv spans in those third party observability backends as well if you'd like to avoid sending abv spans to third party observability backends in your existing opentelemetry setup, you will need to use an isolated opentelemetry tracerprovider that is separate from the global one if you would like to simply limit the spans that are sent to abv and you have no third party observability backend where you’d like to exclude abv spans from, typescript sdk advanced configuration /#filtering spans using an isolated tracerprovider may break the parent child relationships in your traces, as all tracerproviders still share the same active span context for example, if you have an active parent span from the global tracerprovider but children from an isolated tracerprovider, you may see “orphaned” observations in the abv ui consider the impact on trace structure when configuring an isolated tracer provider import { nodetracerprovider } from "@opentelemetry/sdk trace node"; import { setabvtracerprovider } from "@abvdev/tracing"; // create a new tracerprovider and register the abvspanprocessor // do not set this tracerprovider as the global tracerprovider const abvtracerprovider = new nodetracerprovider( spanprocessors \[new abvspanprocessor()], ) // register the isolated tracerprovider setabvtracerprovider(abvtracerprovider) multi project setup you can configure the sdk to send traces to multiple abv projects this is useful for multi tenant applications or for sending traces to different environments simply register multiple abvspanprocessor instances, each with its own credentials instrumentation ts import { nodesdk } from "@opentelemetry/sdk node"; import { abvspanprocessor } from "@abvdev/otel"; const sdk = new nodesdk({ spanprocessors \[ new abvspanprocessor({ apikey "sk abv api key project 1", }), new abvspanprocessor({ apikey "sk abv api key project 2", }), ], }); sdk start(); this configuration will send every trace to both projects you can also configure a custom shouldexportspan filter for each processor to control which traces go to which project custom scores from browser sending custom scores directly from the browser is not yet supported in the typescript sdk