Descubra cómo activar el rastreo y ver rastreos de funciones al depurar con OCI Functions.
Cuando se llama a una función pero no se ejecuta o se ejecuta como se esperaba, debe investigar el problema en un nivel detallado. La función de rastreo distribuido observa la ejecución de la función a medida que se mueve a través de los diferentes componentes del sistema. Puede rastrear e instrumentar funciones independientes para depurar problemas de ejecución y rendimiento. También puede utilizar el rastreo de funciones para depurar problemas con aplicaciones sin servidor completas que incluyen varias funciones y servicios, como:
una función que llama a otra función
una función que llama a otros servicios, como el servicio Object Storage
una función que sirve como backend para un gateway de API desplegado en el servicio de gateway de API
una función disparada en respuesta a un evento por el servicio Events, el servicio Notifications o Connector Hub
Las capacidades de rastreo de OCI Functions las proporciona el servicio Oracle Cloud Infrastructure Application Performance Monitoring. Las funciones de Application Performance Monitoring (APM) permiten identificar y solucionar fallos y problemas de latencia en las funciones que cree y despliegue.
En el servicio Application Performance Monitoring:
Un dominio de APM contiene los sistemas supervisados por Application Performance Monitoring. Un dominio de APM es una instancia de un recopilador de datos de rastreo y período que almacena, agrega, muestra y visualiza los datos.
Un rastreo es el flujo completo de una solicitud que pasa por todos los componentes de un sistema distribuido en un período de tiempo determinado. Consta de un árbol completo de intervalos, todos relacionados con el mismo flujo de solicitud global único.
Un intervalo es una operación o una unidad lógica de trabajo con un nombre, una hora de inicio y una duración, dentro de un rastreo. Un intervalo es un segmento de tiempo asociado con la duración de una unidad de trabajo dentro del flujo de solicitud general.
El explorador de rastreo de Application Performance Monitoring permite visualizar todo el flujo de solicitudes y explorar los detalles de rastreo y período para el diagnóstico. Puede ver y supervisar rastreos lentos y rastreos con errores. Para aislar e identificar incidencias de rastreo, puede aumentar el detalle de períodos específicos, como cargas de páginas, llamadas AJAX y solicitudes de servicio. Para obtener más información sobre el servicio Application Performance Monitoring, consulte Application Performance Monitoring.
Active el rastreo para la aplicación Functions y seleccione el dominio de APM que ha creado.
Active el rastreo para una o más funciones.
Al activar el rastreo para una función, OCI Functions genera automáticamente un "plazo de llamada de función por defecto". El intervalo por defecto captura información sobre el contexto de ejecución de la función, incluido el tiempo total que se tarda en procesar la solicitud y devolver una respuesta al emisor de la llamada. Además del período de llamada de función por defecto, puede agregar código a las funciones para definir períodos personalizados. Utilice intervalos personalizados para capturar más información específica de la función para ayudar con la depuración. Por ejemplo, puede definir intervalos personalizados para capturar el inicio y el final de unidades de trabajo específicas. Por ejemplo, las unidades de trabajo podrían incluir la obtención de la contraseña de base de datos del almacén, la apertura de una conexión a base de datos y la recuperación de registros de la base de datos.
Se han agregado cuatro variables al contexto de OCI Functions que proporcionan información de rastreo útil. Estas variables incluyen:
FN_APP_NAME: Nombre de la aplicación de la función.
FN_FN_NAME: Nombre de función.
OCI_TRACE_COLLECTOR_URL: URL de dominio de APM con clave de datos.
OCI_TRACING_ENABLED: ¿Está activado el rastreo?
Cuando se recupera de variables de entorno, devuelve 0 o 1.
Cuando se recupera del contexto de la función, devuelve true o false según corresponda para el idioma utilizado.
Uso de la consola para activar el rastreo y ver rastreos de funciones
Se necesitan un par de pasos para activar el rastreo y ver los rastreos de funciones para el servicio Oracle Cloud Infrastructure Application Performance Monitoring (APM). En primer lugar, active el rastreo para la aplicación que contiene la función. A continuación, active el rastreo para una o más funciones. A continuación, puede ver los rastreos de funciones en el explorador de rastreo de APM.
Uso de la consola para activar el rastreo 🔗
Para activar el rastreo, siga estos pasos.
En la página de lista Aplicaciones, seleccione la aplicación con funciones para las que desea activar el rastreo. Si necesita ayuda para buscar la página de lista o la aplicación, consulte Listado de aplicaciones.
Para activar el rastreo para la aplicación:
En Recursos, seleccione Rastreos.
Seleccione la opción Rastreo Activado y especifique:
compartimento: compartimento en el que se va a crear el rastreo. Por defecto, el compartimento actual.
Dominio de APM: dominio de APM (definido en el servicio Application Performance Monitoring) en el que crear el rastreo. Para utilizar un dominio de APM existente, seleccione un dominio de APM existente de la lista. O bien, para crear un nuevo dominio de APM, seleccione APM Domain (Dominio de APM). Para obtener más información sobre los dominios de APM, consulte Introducción a Application Performance Monitoring.
Nota
El dominio de APM debe tener claves de datos públicas y privadas para que el rastreo de funciones funcione. Si las claves no existen, puede crearlas a través de la interfaz de la consola.
Seleccione Activar Rastreo para activar el rastreo para la aplicación.
Una vez activado el rastreo para la aplicación de Functions, ahora puede activar el rastreo para una o más funciones de la aplicación.
Para activar el rastreo para funciones específicas en la aplicación:
En Recursos, seleccione Funciones.
Seleccione la opción Activar Rastreo junto a una o más funciones para las que desea activar el rastreo.
La opción Activar Rastreo sólo se muestra si ha activado previamente el rastreo para la aplicación. Tenga en cuenta lo siguiente:
Si no se muestra la opción Activar rastreo, debe activar el rastreo para la aplicación. Si aún no ha activado el rastreo para la aplicación, consulte el paso anterior.
Si activó previamente el rastreo para la aplicación, pero posteriormente lo desactivó, se muestra un enlace Activar rastreo de aplicación. Seleccione el enlace Activar Rastreo de Aplicación para volver a activar el rastreo de la aplicación (consulte el paso anterior). Después de volver a activar el rastreo para la aplicación, puede activar el rastreo para funciones específicas.
Cuando haya activado el rastreo para la aplicación y una o más funciones, puede ver los rastreos de funciones.
Uso de la consola para ver rastreos de funciones
Para ver los rastreos de las funciones que tienen el rastreo activado:
En la página de lista Aplicaciones, seleccione la aplicación que contiene las funciones para las que desea ver rastreos. Si necesita ayuda para buscar la página de lista o la aplicación, consulte Listado de aplicaciones.
Para ver rastreos de funciones:
Para ver los rastreos de todas las funciones que tienen el rastreo activado en la aplicación:
En Recursos, seleccione Rastreos.
Seleccione el nombre del rastreo.
Nota
Un nombre de rastreo solo se muestra si ya ha activado el rastreo para la aplicación.
Para ver el rastreo de una función específica que tiene el rastreo activado:
En Recursos, seleccione Funciones.
Seleccione el menú Acciones () junto a la función y, a continuación, seleccione Ver Rastreo.
Nota
La opción Ver rastreo solo se muestra si ya ha activado el rastreo para la función.
Los rastreos de las funciones seleccionadas se muestran en el explorador de rastreo de APM. Por defecto, se muestra un rastreo para el intervalo de llamada a la función por defecto y cualquier intervalo personalizado definido para la función.
En el explorador de rastreo de APM:
Seleccione un rastreo para ver los intervalos de ese rastreo.
Seleccione un período para ver los detalles capturados para ese período.
Por defecto, el rastreo de funciones proporciona un rastreo para una llamada de función completa. Sin embargo, a menudo con las aplicaciones modernas en la nube, necesita encadenar llamadas a funciones. El rastreo de OCI Functions proporciona la capacidad de rastrear la ejecución de una función llamada por otra función. Esta capacidad significa que puede examinar la ejecución de cada función en una cadena de llamadas en un solo árbol de intervalos en el explorador de rastreo de APM.
Para rastrear una cadena de funciones, debe propagar las cabeceras X-B3 X-B3-TraceId, X-B3-SpanId, X-B3-ParentSpanId y X-B3-Sampled en la solicitud de llamada de función desde el código de función.
Una vez ejecutada la función, los datos de rastreo de las funciones se recopilan y están disponibles en el explorador de rastreo de APM. Para obtener más información sobre el uso del explorador de rastreo de APM, consulte Uso del explorador de rastreo.
A continuación, se muestra un ejemplo de cómo puede rastrear una cadena de funciones. Si desea probar este ejemplo, debe crear dos funciones de ejemplo. Siga estos pasos para configurar las funciones.
Cree la función de rastreo de Python: fn init --runtime python <your-function-name-1>
Obtenga el OCID de la segunda función y llame al punto final: fn inspect function your-app-name your-function-name-2
Cree un archivo JSON para transferir la información necesaria a la primera función. Por ejemplo, el archivo test.json podría tener el siguiente aspecto:
Copiar
{
"function_ocid": "ocid1.fnfunc.oc1.iad.aaaaaaaaxxxxxxxxxxx",
"function_endpoint": "https://xxxxxxxxx.us-ashburn-1.functions.oci.oraclecloud.com",
"function_body": "",
"__comment": "Alternatively, you can set function_body to { \"name\": \"Oracle\" }"
}
Cuando se llama a la primera función, puede transferir la información de la segunda función mediante test.json: fn invoke <app-name> <your-function-name-1> < test.json
Ahora está listo para actualizar la primera función con las actualizaciones de código necesarias.
Configurar paquetes 🔗
Actualice el archivo requirements.txt para incluir los siguientes paquetes:
Copiar
fdk
oci
Guardar el archivo.
Actualización del código de función para propagar las cabeceras X-B3 🔗
La función Python llama a la función handler y transfiere la información de JSON desde el comando de llamada. La función handler se divide en varios bloques pequeños para simplificarla. El archivo de origen completo se proporciona en la parte inferior de esta sección.
Cargar los datos de JSON 🔗
En esta primera parte, los datos de JSON se cargan desde la llamada a la función.
Creación de Llamada de Cliente y Recopilación de Información de Cabecera 🔗
Cree el cliente de llamada de Functions mediante el SDK de Python de OCI y los principales de recursos de Functions. A continuación, recupere tracing_context y extraiga la información necesaria para crear las cabeceras HTTP.
El SDK de Python de OCI le permite definir cabeceras personalizadas. Utilice esta técnica para transferir las cabeceras X-B3 a la segunda llamada de función. La información de cabecera se transfiere para trace_id, span_id, parent_span_id y is_sampled. Por último, se llama a la segunda función con client y la respuesta se transfiere a la respuesta de esta función.
Copiar
# if tracing is enabled, is_sampled will be true in the tracing context
if is_sampled:
# To propagate headers in the OCI SDK in the request to the next function,
# add the X-B3- headers in the request. This header will be included in ALL
# subsequent calls made.
if trace_id is not None:
client.base_client.session.headers['X-B3-TraceId'] = trace_id
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | trace_id: " + trace_id)
if span_id is not None:
client.base_client.session.headers['X-B3-SpanId'] = span_id
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | span_id: " + span_id)
if parent_span_id is not None:
client.base_client.session.headers['X-B3-ParentSpanId'] = parent_span_id
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | parent_span_id: " + parent_span_id)
client.base_client.session.headers['X-B3-Sampled'] = str(int(is_sampled))
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | is_sampled: " + str(int(is_sampled)))
else:
# function.trace is DISABLED
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | function tracing is DISABLED")
resp = client.invoke_function(function_id=function_ocid, invoke_function_body=function_body)
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | Response: " + resp.data.text)
return response.Response(
ctx,
response_data=resp.data.text,
headers={"Content-Type": "application/json"}
)
Este es el código fuente completo para la función de Python de ejemplo.
Copiar
#
# oci-invoke-function-python version 2.0.
#
# Copyright (c) 2021 Oracle, Inc.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
#
import io
import json
import logging
import oci
from fdk import response
def handler(ctx, data: io.BytesIO=None):
app_name = ctx.AppName()
func_name = ctx.FnName()
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler")
try:
body = json.loads(data.getvalue())
function_endpoint = body.get("function_endpoint")
function_ocid = body.get("function_ocid")
function_body = body.get("function_body")
except (Exception) as ex:
print('ERROR: Missing key in payload', ex, flush=True)
raise
signer = oci.auth.signers.get_resource_principals_signer()
client = oci.functions.FunctionsInvokeClient(config={}, signer=signer, service_endpoint=function_endpoint)
#
# Zipkin X-B3- header propagation
#
tracing_context = ctx.TracingContext()
trace_id = tracing_context.trace_id()
span_id = tracing_context.span_id()
parent_span_id = tracing_context.parent_span_id()
is_sampled = tracing_context.is_sampled()
# if tracing is enabled, is_sampled will be true in the tracing context
if is_sampled:
# To propagate headers in the OCI SDK in the request to the next function,
# add the X-B3- headers in the request. This header will be included in ALL
# subsequent calls made.
if trace_id is not None:
client.base_client.session.headers['X-B3-TraceId'] = trace_id
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | trace_id: " + trace_id)
if span_id is not None:
client.base_client.session.headers['X-B3-SpanId'] = span_id
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | span_id: " + span_id)
if parent_span_id is not None:
client.base_client.session.headers['X-B3-ParentSpanId'] = parent_span_id
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | parent_span_id: " + parent_span_id)
client.base_client.session.headers['X-B3-Sampled'] = str(int(is_sampled))
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | is_sampled: " + str(int(is_sampled)))
else:
# function.trace is DISABLED
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | function tracing is DISABLED")
resp = client.invoke_function(function_id=function_ocid, invoke_function_body=function_body)
logging.getLogger().info("Inside app: " + app_name + " | function: " + func_name + " | method: handler | Response: " + resp.data.text)
return response.Response(
ctx,
response_data=resp.data.text,
headers={"Content-Type": "application/json"}
)
Adición de períodos personalizados a funciones 🔗
Con el rastreo de funciones activado, el período de llamada a la función por defecto proporciona un rastreo para toda la llamada a la función. El intervalo por defecto puede proporcionar buena información, pero al investigar el código puede que desee profundizar más. Los intervalos personalizados se agregan directamente al código y le permiten definir intervalos para un método o un bloque de código. Los datos resultantes proporcionan una mejor imagen de su función a medida que se ejecuta.
Para poder utilizar períodos personalizados, debe activar el rastreo para la aplicación y las funciones mediante el servicio Oracle Cloud Infrastructure Application Performance Monitoring (APM). Para definir el rastreo, debe:
A continuación, se muestra un ejemplo de cómo utilizar Zipkin para agregar períodos personalizados a la función Java. Si desea probar este ejemplo, puede crear una función "Hello World!" de Java y agregar código de período personalizado. Para crear una función de ejemplo:
Cree una función Java: fn init --runtime java apm-fn-java
Para simplificar, elimine el directorio src/test.
Configurar Maven 🔗
Agregue las siguientes dependencias a la sección <dependencies> del archivo pom.xml de Maven.
traceContext se transfiere para crear todos los objetos utilizados para crear períodos personalizados.
apmURL se recupera del método getTraceCollectorURL(). La URL es el punto final del dominio de APM y se utiliza para crear el objeto tracer que crea los períodos personalizados.
Un creador toma zipkinSpanHandler y el nombre del servicio para crear un objeto tracer. Este objeto tracer se utiliza para crear períodos personalizados.
Creación de períodos personalizados 🔗
Con el objeto tracer inicializado, se pueden crear períodos personalizados.
A continuación, se muestra un ejemplo de cómo utilizar Zipkin para agregar períodos personalizados a la función de Python. Si desea probar este ejemplo, puede crear una función "Hello World!" de Python y agregar código de período personalizado. Para crear una función de ejemplo:
Crear una función de Python: fn init --runtime python apm-fn-python
Configurar paquetes 🔗
Actualice el archivo requirements.txt para incluir los siguientes paquetes:
Copiar
fdk
requests
py_zipkin
Guardar el archivo.
Creación de Clase de Manejador y Intervalo Personalizado Principal 🔗
La función Python llama a la función handler y transfiere en el contexto de la función para crear períodos personalizados.
tracing_context se transfiere desde el contexto de la función y contiene toda la información necesaria para crear y configurar períodos personalizados.
Nota
Si el rastreo no está activado, el contexto de rastreo es un objeto vacío. Con un contexto de rastreo vacío, el indicador is_sampled se define en None y py_zipkin no emite períodos.
La sentencia with zipkin_span se utiliza para crear períodos.
La información de tracing_context se utiliza para obtener service_name, llamar a transport_handler y definir zipking_attrs.
Se especifica un nombre de período personalizado simplemente definiendo span_name.
Los atributos de rastreo necesarios para Zipkin se recuperan del contexto de rastreo: tracing_context.zipkin_attrs().
Con la configuración personalizada del intervalo, el bloque principal ejecuta el código fijo "Hello World!" Con la única excepción, una llamada a la función example.
La función transport_handler 🔗
La función transport_handler se comunica con el dominio de APM con mensajes sobre la ejecución del período.
Copiar
# transport handler, needed by py_zipkin
def transport_handler(encoded_span, tracing_context):
return requests.post(
tracing_context.trace_collector_url(),
data=encoded_span,
headers={"Content-Type": "application/json"},
)
trace_collector_url se devuelve desde el contexto de la función. Esta URL proporciona el punto final de comunicación para los períodos personalizados al dominio de APM.
Creación de un intervalo personalizado en una función de ejemplo 🔗
La función de ejemplo muestra la creación de un período personalizado.
Copiar
def example(ctx):
with zipkin_span(
service_name=ctx.TracingContext().service_name(),
span_name="Get ADB Password from OCI Vault",
binary_annotations=ctx.TracingContext().annotations()
) as example_span_context:
try:
logging.getLogger().debug("Get ADB Password from OCI Vault")
time.sleep(0.005)
# throwing an exception to show how to add error messages to spans
raise Exception('Request failed')
except (Exception, ValueError) as error:
example_span_context.update_binary_annotations(
{"Error": True, "errorMessage": str(error)}
)
else:
FakeResponse = namedtuple("FakeResponse", "status, message")
fakeResponse = FakeResponse(200, "OK")
# how to update the span dimensions/annotations
example_span_context.update_binary_annotations(
{
"responseCode": fakeResponse.status,
"responseMessage": fakeResponse.message
}
)
La sentencia with zipkin_span se utiliza para identificar el período personalizado y asignarle un nombre.
El bloque example_span_context emite una excepción y devuelve un mensaje de error.
A continuación, se muestra un ejemplo de cómo utilizar Zipkin para agregar períodos personalizados a la función Node.js. Si desea probar este ejemplo, puede crear una función "Hello World!" del nodo y agregar código de intervalo personalizado. Para crear una función de ejemplo:
Crear una función de nodo: fn init --runtime node apm-fn-node
Configurar dependencias de nodos 🔗
Actualice el archivo package.json para incluir los siguientes paquetes:
Las observaciones clave sobre el método fdk.handle siguen el código fuente.
Copiar
// ZipkinJS core components.
const {
ExplicitContext,
Annotation,
Tracer,
TraceId,
BatchRecorder,
jsonEncoder,
sampler,
option
} = require('zipkin');
// An HTTP transport for dispatching Zipkin traces.
const {HttpLogger} = require('zipkin-transport-http');
fdk.handle(async function(input, ctx){
tracer = createOCITracer(ctx);
var result;
// Start a new 'scoped' server handling span.
await tracer.scoped(async function () {
// Fetch some resource
result = await tracer.local('fetchResource', () => {
return fetchResource();
});
// Perform some processing
result = await tracer.local('processResource', () => {
return someComputation(result);
});
// Update some resource
result = await tracer.local('updateResource', () => {
return updateResource(result);
});
await flush();
});
return result;
})
tracer se crea y, a continuación, se utiliza para crear un período personalizado principal. A continuación, se crean intervalos secundarios para las funciones fetchResource, processResource y updateResource.
Revisión de la función createOCITracer 🔗
Las observaciones clave sobre la función siguen el código fuente.
Copiar
/**
* Creates a basic Zipkin Tracer using values from context of the function
* invocation.
*
* @param {*} ctx The function invocation context.
* @returns A configured Tracer for automatically tracing calls.
*/
function createOCITracer (ctx) {
// An OCI APM configured Tracer
//
const tracingCxt = ctx.tracingContext
const tracer = new Tracer({
ctxImpl: new ExplicitContext(),
recorder: new BatchRecorder({
logger: new HttpLogger({
// The configured OCI APM endpoint is available in the function
// invocation context.
endpoint: tracingCxt.traceCollectorUrl,
jsonEncoder: jsonEncoder.JSON_V2
})
}),
// APM Dimensions that should be included in all traces can be configured
// directly on Tracer.
defaultTags: createOCITags(ctx),
// A custom sampling strategy can be defined.
sampler: createOCISampler(ctx),
localServiceName: tracingCxt.serviceName,
supportsJoin: true,
traceId128Bit: true
})
// The initial function invocation trace identifiers can be added directly.
// If this is not defined a default TraceId is created.
const traceId = createOCITraceId(tracer, ctx)
tracer.setId(traceId)
return tracer
}
El contexto de función (ctx) se transfiere a esta función, que proporciona la información necesaria para conectarse al dominio de APM. Si sigue las llamadas de función, puede ver cómo se crean los ID de rastreo y los campos.
Este es el código fuente completo para la función de rastreo de nodos de ejemplo.
Copiar
const fdk = require('@fnproject/fdk')
// ZipkinJS core components.
const {
ExplicitContext,
Tracer,
TraceId,
BatchRecorder,
jsonEncoder,
sampler,
option
} = require('zipkin')
// An HTTP transport for dispatching Zipkin traces.
const { HttpLogger } = require('zipkin-transport-http')
fdk.handle(async function (input, ctx) {
var tracer = createOCITracer(ctx)
var result
// Start a new 'scoped' server handling span.
await tracer.scoped(async function () {
// Fetch some resource
result = await tracer.local('fetchResource', () => {
return fetchResource()
})
// Perform some processing
result = await tracer.local('processResource', () => {
return someComputation(result)
})
// Update some resource
result = await tracer.local('updateResource', () => {
return updateResource(result)
})
await flush()
})
return result
})
// ----------------------------------------------------------------------------
// App Simulation Functions
//
/**
* Simulate fetching some required resource. This could be another OCI service
* or an external call.
*
* @returns A Promise with the success or failure of the operation.
*/
function fetchResource () {
return simulate(1000, { fetchResource: 'OK' })
}
/**
* Simulate some work. This could be another OCI service.
*
* @returns A Promise with the success or failure of the operation.
*/
async function someComputation (toReturn) {
var i
for (i = 0; i < 5; i++) {
await simulate(1000)
}
toReturn.processResource = 'OK'
return toReturn
}
/**
* Simulate updating some resource. This could be another OCI service or an
* external call.
*
* @returns A Promise with the success or failure of the operation.
*/
async function updateResource (toReturn) {
await simulate(500)
toReturn.updateResource = 'OK'
return toReturn
}
/**
* A helper function to simulate an operation that takes a specified amount of time.
*
* @param {*} ms The simulated time for the activity in milliseconds.
* @returns A promise that resolves when the simulated activity finishes.
*/
function simulate (ms, result) {
return new Promise(resolve => setTimeout(resolve, ms, result))
}
/**
* Functions service may freeze or terminate the container on completion.
* This function gives extra time to allow the runtime to flush any pending traces.
* See: https://github.com/openzipkin/zipkin-js/issues/507
*
* @returns A Promise to await on.
*/
function flush () {
return new Promise(resolve => setTimeout(resolve, 1000))
}
// ----------------------------------------------------------------------------
// OpenZipkin ZipkinJS Utility Functions
//
/**
* Creates a basic Zipkin Tracer using values from context of the function
* invocation.
*
* @param {*} ctx The function invocation context.
* @returns A configured Tracer for automatically tracing calls.
*/
function createOCITracer (ctx) {
// An OCI APM configured Tracer
//
const tracingCxt = ctx.tracingContext
const tracer = new Tracer({
ctxImpl: new ExplicitContext(),
recorder: new BatchRecorder({
logger: new HttpLogger({
// The configured OCI APM endpoint is available in the function
// invocation context.
endpoint: tracingCxt.traceCollectorUrl,
jsonEncoder: jsonEncoder.JSON_V2
})
}),
// APM Dimensions that should be included in all traces can be configured
// directly on Tracer.
defaultTags: createOCITags(ctx),
// A custom sampling strategy can be defined.
sampler: createOCISampler(ctx),
localServiceName: tracingCxt.serviceName,
supportsJoin: true,
traceId128Bit: true
})
// The initial function invocation trace identifiers can be added directly.
// If this is not defined a default TraceId is created.
const traceId = createOCITraceId(tracer, ctx)
tracer.setId(traceId)
return tracer
}
/**
* A ZipkinJS 'TraceId' can be created directly from the function invocation
* context.
*
* @param {*} ctx The function invocation context.
* @returns A ZipkinJS 'TraceId' created from the invocation context.
*/
function createOCITraceId (tracer, ctx) {
const tracingCxt = ctx.tracingContext
if (tracingCxt.traceId && tracingCxt.spanId) {
return new TraceId({
traceId: tracingCxt.traceId,
spanId: tracingCxt.spanId,
sampled: new option.Some(tracingCxt.sampled),
debug: new option.Some(tracingCxt.debug),
shared: false
})
} else {
return tracer.createRootId(
new option.Some(tracingCxt.sampled),
new option.Some(tracingCxt.debug)
)
}
}
/**
* A ZipkinJS 'TraceId' can be crated directly from the function invocation
* context.
*
* This configurations will automatically add the function meta-data as APM
* dimensions to each trace. Function environment variable and other dimensions
* could also be added.
*
* @param {*} ctx The function invocation context.
* @returns A map of key-value pairs, that will be added as APM
* dimensions to the traces.
*/
function createOCITags (ctx) {
return {
appID: ctx.appID,
appName: ctx.appName,
fnID: ctx.fnID,
fnName: ctx.fnName
}
}
/**
* A ZipkinJS 'Sampler' can be created directly from the function invocation
* context.
*
* This configuration will only create a trace if the function is configured
* for tracing.
*
* @param {*} ctx The function invocation context.
* @returns A ZipkinJS 'TraceId' created from the invocation context.
*/
function createOCISampler (ctx) {
return new sampler.Sampler((traceId) => ctx.tracingContext.isEnabled)
}