UNPKG

@ogcio/o11y-sdk-node

Version:

Opentelemetry standard instrumentation SDK for NodeJS based project

82 lines (81 loc) 3.15 kB
import { context, defaultTextMapGetter, propagation, } from "@opentelemetry/api"; import { encodeGeohash } from "./geohash.js"; export const geoBaggageKeys = ["geo.country", "geo.city", "geo.hash"]; /** * CloudFront viewer header names carrying geo information. * @see https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/adding-cloudfront-headers.html */ export const CF_GEO_HEADERS = { COUNTRY: "cloudfront-viewer-country", CITY: "cloudfront-viewer-city", LATITUDE: "cloudfront-viewer-latitude", LONGITUDE: "cloudfront-viewer-longitude", }; /** Reads a single header value, collapsing multi-valued headers to their first entry. */ export function getHeaderValue(carrier, key, getter = defaultTextMapGetter) { const value = getter.get(carrier, key); return Array.isArray(value) ? value[0] : value; } function fromBaggage(baggage) { if (!baggage) return {}; const attrs = {}; for (const key of geoBaggageKeys) { const value = baggage.getEntry(key)?.value; if (value) attrs[key] = value; } return attrs; } /** * Returns geo attributes from the given OTel context's baggage. * Use this in span and log processors where the context is passed explicitly. */ export function getGeoAttributesFromContext(ctx) { return fromBaggage(propagation.getBaggage(ctx)); } /** * Returns geo attributes for the current request context. * Reads from OTel Baggage on the active context, set by GeoBaggagePropagator. * Use this to manually enrich custom spans, logs, or metrics when geo-enrichment is enabled. */ export function getGeoAttributes() { return fromBaggage(propagation.getBaggage(context.active())); } /** * Builds geo attributes from any combination of geo inputs. * A geohash is computed automatically when both `lat` and `lon` are provided. * Use this to create geo attributes to attach to signals when auto-enrichment is not enabled. */ export function createGeoAttributesFrom(input) { const attrs = {}; if (input.country) { attrs["geo.country"] = input.country; } if (input.city) { attrs["geo.city"] = input.city; } const hash = encodeGeohash(input.lat, input.lon, input.precision); if (hash) { attrs["geo.hash"] = hash; } return attrs; } /** * Builds geo attributes directly from provider headers. * Use this to enrich a single span, log, or metric when auto-enrichment is not enabled. */ export function createGeoAttributesFromHeaders(carrier, options = {}) { const { getter = defaultTextMapGetter, precision, headerMap = CF_GEO_HEADERS, } = options; const country = getHeaderValue(carrier, headerMap.COUNTRY, getter); const city = getHeaderValue(carrier, headerMap.CITY, getter); const latStr = getHeaderValue(carrier, headerMap.LATITUDE, getter); const lonStr = getHeaderValue(carrier, headerMap.LONGITUDE, getter); return createGeoAttributesFrom({ country, city, lat: latStr !== undefined ? parseFloat(latStr) : undefined, lon: lonStr !== undefined ? parseFloat(lonStr) : undefined, precision, }); }