After you enable Tracing Analysis for a service, Function Compute automatically records the time consumed in the system. The time includes the cold start time, execution time of an initializer function, and execution time of a function. To record the time consumed for the function on the business side, you can create custom spans. For example, you can record the time taken to access services such as ApsaraDB RDS and Apsara File Storage NAS within the function.

Procedure

You can create custom spans based on the trace of Function Compute and connect the custom spans to the trace. Tracing Analysis for Function Compute provides the following two methods to create custom spans based on the Jaeger implementation of the OpenTracing specification:

For more information about Jaeger and OpenTelemetry, see Jaeger and OpenTelemetry.

The two methods involve the following steps:

  1. Add Jaeger or OpenTelemetry dependencies to the function. For more information about how to add third-party dependencies, see Install third-party dependencies on Function Compute.
  2. Obtain the SpanContext of the trace from the function, create custom spans based on the SpanContext, and then add instrumentation before and after the code fragments whose execution time needs to be recorded.
  3. View the trace information on the Traces tab of the function details page in the Function Compute console or in the Tracing Analysis console.

Use the SDK for Jaeger

This topic uses the Node.js run time as an example to describe how to use Serverless Devs to create a custom Span. Steps to create and deploy a function.

Note You can use Serverless Devs to install dependency package and package and deploy them to Function Compute. You can also package and deploy them in other ways. For more information about Serverless Devs, see Overview.
  1. Create a code directory.
    mkdir jaeger-demo
  2. Initialize a Node.js runtime template.
    1. Run the following command to go to the code directory:
      cd jaeger-demo
    2. Run the following command in the code directory to initialize the Node.js 12 project:
      s init devsapp/start-fc-event-nodejs12
      Sample command output:
       Serverless Awesome: https://github.com/Serverless-Devs/package-awesome
      
       Please input your project name (init dir) (start-fc-event-nodejs12)
    3. Set the project name and press the Enter key.
      Serverless Devs has generated a project named start-fc-event-nodejs12 by default. You can modify the project name as needed. This topic uses the default project name as an example.
      Sample command output:
       Serverless Awesome: https://github.com/Serverless-Devs/package-awesome
      
       Please input your project name (init dir) start-fc-event-nodejs12
       file decompression completed
       please select credential alias (Use arrow keys)
      ❯ default
    4. Select an alias as needed, and then press the Enter key.
    5. Select whether to deploy the project as needed.
      Since the project described in this example also needs to install dependencies, do you want to deploy the project immediately in? After (Y/n), set the n and select not to deploy the project.
  3. Run the following command to perform the code directory of the project:
    cd start-fc-event-nodejs12/code
  4. In the code directory, run the following command to initialize the package.json file:
    npm init -y
    Sample command output:
    Wrote to /test/jjyy/start-fc-event-nodejs12/code/package.json:
    
    {
      "name": "code",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
  5. Run the following command to install the Jaeger dependency:
    npm i jaeger-client --save
    Sample command output:
    added 15 packages in 1s
  6. Edit the function code.
    The code content is as follows:
    var initTracer = require('jaeger-client').initTracer;
    var spanContext = require('jaeger-client').SpanContext;
    
    
    module.exports.handler = function(event, context, callback) 
    {
        console.log('invoking...',context.tracing);
    
        var config = {
            serviceName: 'e2e-test',
            reporter: {
                // Provide the traces endpoint; this forces the client to connect directly to the Collector and send
                // spans over HTTP
                collectorEndpoint: context.tracing.jaegerEndpoint,
                flushIntervalMs: 10,
            },
            sampler: {
                type: "const",
                param: 1
            },
        };
        var options = {
            tags: {
                'version': 'fc-e2e-tags',
            },
        };
        var tracer = initTracer(config, options);
        var invokSpanContextStr = context.tracing.openTracingSpanContext;
        console.log('spanContext', invokSpanContextStr);
        var invokSpanContext = spanContext.fromString(invokSpanContextStr);
        var span = tracer.startSpan("CustomSpan", {
            childOf: invokSpanContext
        });
        span.finish();
        var params = {
            openTracingSpanContext: context.tracing.openTracingSpanContext,
            openTracingSpanBaggages: context.tracing.openTracingSpanBaggages,
            jaegerEndpoint: context.tracing.jaegerEndpoint
        }
       callback(null,'success')
    }
  7. Install dependencies.
    1. Run the following command to go to the project directory:
      cd ..
    2. Run the following command to install dependencies:
      s build --use-docker
      Sample command output:
      [2021-11-12T18:33:43.856] [INFO ] [S-CLI] - Start ...
      [2021-11-12T18:33:44.677] [INFO ] [FC-BUILD] - Build artifact start...
      [2021-11-12T18:33:44.701] [INFO ] [FC-BUILD] - Use docker for building.
      [2021-11-12T18:33:44.988] [INFO ] [FC-BUILD] - Build function using image: registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-nodejs12:build-1.9.21
      [2021-11-12T18:33:45.011] [INFO ] [FC-BUILD] - skip pulling image registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-nodejs12:build-1.9.21...
      [2021-11-12T18:33:47.915] [INFO ] [FC-BUILD] - Build artifact successfully.
      
      Tips for next step
      ======================
      * Invoke Event Function: s local invoke
      * Invoke Http Function: s local start
      * Deploy Resources: s deploy
      End of method: build
  8. Run the following command to deploy the project:
    s deploy -y
    Sample command output:
    [2021-11-12T18:35:26.015] [INFO ] [S-CLI] - Start ...
    [2021-11-12T18:35:26.633] [INFO ] [FC-DEPLOY] - Using region: cn-hangzhou
    [2021-11-12T18:35:26.634] [INFO ] [FC-DEPLOY] - Using access alias: default
    [2021-11-12T18:35:26.634] [INFO ] [FC-DEPLOY] - Using accessKeyID: LTAI4G4cwJkK4Rza6xd9****
    [2021-11-12T18:35:26.634] [INFO ] [FC-DEPLOY] - Using accessKeySecret: eCc0GxSpzfq1DVspnqqd6nmYNN****
     Using fc deploy type: sdk, If you want to deploy with pulumi, you can [s cli fc-default set deploy-type pulumi] to switch.
    [2021-11-12T18:35:26.875] [INFO ] [FC-DEPLOY] - Checking Service fc-deploy-service exists
    [2021-11-12T18:35:27.202] [INFO ] [FC-DEPLOY] - Checking Function event-nodejs12 exists
    [2021-11-12T18:35:27.286] [INFO ] [FC-DEPLOY] - Fc detects that you have run build command for function: event-nodejs12.
    [2021-11-12T18:35:27.290] [INFO ] [FC-DEPLOY] - Using codeUri: /test/jjyy/start-fc-event-nodejs12/.s/build/artifacts/fc-deploy-service/event-nodejs12
    [2021-11-12T18:35:27.293] [INFO ] [FC-DEPLOY] - Fc add/append some content to your origin environment variables for finding dependencies generated by build command.
    {
      "LD_LIBRARY_PATH": "/code/.s/root/usr/local/lib:/code/.s/root/usr/lib:/code/.s/root/usr/lib/x86_64-linux-gnu:/code/.s/root/usr/lib64:/code/.s/root/lib:/code/.s/root/lib/x86_64-linux-gnu:/code/.s/root/python/lib/python2.7/site-packages:/code/.s/root/python/lib/python3.6/site-packages:/code:/code/lib:/usr/local/lib",
      "PATH": "/code/.s/root/usr/local/bin:/code/.s/root/usr/local/sbin:/code/.s/root/usr/bin:/code/.s/root/usr/sbin:/code/.s/root/sbin:/code/.s/root/bin:/code:/code/node_modules/.bin:/code/.s/python/bin:/code/.s/node_modules/.bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/sbin:/bin",
      "NODE_PATH": "/code/node_modules:/usr/local/lib/node_modules",
      "PYTHONUSERBASE": "/code/.s/python"
    }
     Make service fc-deploy-service success.
     Make function fc-deploy-service/event-nodejs12 success.
    [2021-11-12T18:35:37.661] [INFO ] [FC-DEPLOY] - Checking Service fc-deploy-service exists
    [2021-11-12T18:35:37.718] [INFO ] [FC-DEPLOY] - Checking Function event-nodejs12 exists
    
    Tips for next step
    ======================
    * Display information of the deployed resource: s info
    * Display metrics: s metrics
    * Display logs: s logs
    * Invoke remote function: s invoke
    * Remove Service: s remove service
    * Remove Function: s remove function
    * Remove Trigger: s remove trigger
    * Remove CustomDomain: s remove domain
    
    
    
    fc-deploy-test:
      region:   cn-hangzhou
      service:
        name: fc-deploy-service
      function:
        name:       event-nodejs12
        runtime:    nodejs12
        handler:    index.handler
        memorySize: 128
        timeout:    60
  9. Verify the result.
    View the trace in the Function Compute console. The custom span that you created is connected to the spans of Function Compute. user-defined-span

Use OpenTelemetry

This topic uses a Python run time as an example to describe how to use Serverless Devs to create a custom Span, create and deploy a function.

Note You can use Serverless Devs to install dependency package and package and deploy them to Function Compute. You can also package and deploy them in other ways. For more information about Serverless Devs, see Overview.
  1. Create a code directory.
    mkdir opentelemetry-demo
  2. Go to the code directory.
    cd opentelemey-demo
  3. Initialize a Python runtime template.
    1. Run the following command to initialize the Python 3 project:
      s init devsapp/start-fc-event-python3
      Sample command output:
       Serverless Awesome: https://github.com/Serverless-Devs/package-awesome
      
       Please input your project name (init dir) (start-fc-event-python3)
    2. Set the project name and press the Enter key.
      Serverless Devs has generated a project named start-fc-event-python3 for you by default. You can modify the name as needed. This topic uses the default project name as an example.
      Sample command output:
       Serverless Awesome: https://github.com/Serverless-Devs/package-awesome
      
       Please input your project name (init dir) start-fc-event-python3
       file decompression completed
       please select credential alias (Use arrow keys)
      ❯ default
    3. Select an alias as needed, and then press the Enter key.
    4. Select whether to deploy the project as needed.
      Since the project described in this example also needs to install dependencies, do you want to deploy the project immediately in? After (Y/n), set the n and select not to deploy the project.
  4. Install the OpenTelemetry dependencies.
    1. Run the following command to go to the code directory:
      cd start-fc-event-python3/code
    2. Create a requirements.txt file in the code directory, and then edit the file. The file content is as follows:
      opentelemetry-api==1.6.2
  5. Edit the function code.
    Run the following command to edit the function code:
    vim index.py
    The function code content is as follows:
    # -*- coding: utf-8 -*-
    import logging
    import time
    from opentelemetry import trace
    from opentelemetry.exporter import jaeger
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import BatchExportSpanProcessor
    from opentelemetry.trace import set_span_in_context
    
    trace.set_tracer_provider(TracerProvider())
    tracer = trace.get_tracer(__name__)
    
    
    def handler(event, context):
        logger = logging.getLogger()
        logger.info("start to init tracer")
        init_tracer(context.tracing.jaeger_endpoint)
        jaeger_span_context = context.tracing.span_context
        fc_invocation_span = get_fc_span(jaeger_span_context)
        with fc_invocation_span as parent:
            print('Hello world!')
        context = set_span_in_context(parent)
        child = tracer.start_span("child", context=context)
        # print(child)
        time.sleep(0.1)
        child.end()
        return 'hello world'
    
    
    def init_tracer(endpoint):
        jaeger_exporter = jaeger.JaegerSpanExporter(
            service_name='opentelemetry-service',
            collector_endpoint=endpoint,
            transport_format='thrift'  # optional
        )
    
        # Create a BatchExportSpanProcessor and add the exporter to it
        span_processor = BatchExportSpanProcessor(jaeger_exporter)
    
        # add to the tracer
        trace.get_tracer_provider().add_span_processor(span_processor)
    
    
    def get_fc_span(jaeger_span_context):
        jaeger_span_context_arr = jaeger_span_context.split(":")
        tid = int(jaeger_span_context_arr[0], 16)
        sid = int(jaeger_span_context_arr[1], 16)
        fid = int(jaeger_span_context_arr[3], 16)
    
        span_context = trace.SpanContext(
            trace_id=tid,
            span_id=sid,
            is_remote=True,
            trace_flags=trace.TraceFlags(fid),
            trace_state=[],
        )
        return trace.DefaultSpan(span_context)
    Notice After you have edited the function code, run the following command and press the Enter key to exit the editing page:
    :WQ
  6. Install dependencies.
    1. Run the following command to go to the project directory:
      cd ..
    2. Run the following command to install dependencies:
      s build --use-docker
      Sample command output:
      [2021-11-12T18:53:05.818] [INFO ] [S-CLI] - Start ...
      [2021-11-12T18:53:06.638] [INFO ] [FC-BUILD] - Build artifact start...
      [2021-11-12T18:53:06.659] [INFO ] [FC-BUILD] - Use docker for building.
      [2021-11-12T18:53:06.888] [INFO ] [FC-BUILD] - Build function using image: registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-python3.6:build-1.9.21
      [2021-11-12T18:53:06.942] [INFO ] [FC-BUILD] - skip pulling image registry.cn-beijing.aliyuncs.com/aliyunfc/runtime-python3.6:build-1.9.21...
      [2021-11-12T18:53:10.570] [INFO ] [FC-BUILD] - Build artifact successfully.
      
      Tips for next step
      ======================
      * Invoke Event Function: s local invoke
      * Invoke Http Function: s local start
      * Deploy Resources: s deploy
      End of method: build
  7. Deploy the project.
    Run the following command to deploy the project:
    s deploy -y
    Sample command output:
    [2021-11-12T18:55:02.640] [INFO ] [S-CLI] - Start ...
    [2021-11-12T18:55:03.455] [INFO ] [FC-DEPLOY] - Using region: cn-hangzhou
    [2021-11-12T18:55:03.456] [INFO ] [FC-DEPLOY] - Using access alias: default
    [2021-11-12T18:55:03.456] [INFO ] [FC-DEPLOY] - Using accessKeyID: LTAI4G4cwJkK4Rza6xd9****
    [2021-11-12T18:55:03.457] [INFO ] [FC-DEPLOY] - Using accessKeySecret: eCc0GxSpzfq1DVspnqqd6nmYNN****
     Using fc deploy type: sdk, If you want to deploy with pulumi, you can [s cli fc-default set deploy-type pulumi] to switch.
    [2021-11-12T18:55:04.142] [INFO ] [FC-DEPLOY] - Checking Service fc-deploy-service exists
    [2021-11-12T18:55:04.722] [INFO ] [FC-DEPLOY] - Checking Function event-py3 exists
    [2021-11-12T18:55:04.831] [INFO ] [FC-DEPLOY] - Fc detects that you have run build command for function: event-py3.
    [2021-11-12T18:55:04.831] [INFO ] [FC-DEPLOY] - Using codeUri: /test/jjyy/opentelemetry-demo/start-fc-event-python3/.s/build/artifacts/fc-deploy-service/event-py3
    [2021-11-12T18:55:04.835] [INFO ] [FC-DEPLOY] - Fc add/append some content to your origin environment variables for finding dependencies generated by build command.
    {
      "LD_LIBRARY_PATH": "/code/.s/root/usr/local/lib:/code/.s/root/usr/lib:/code/.s/root/usr/lib/x86_64-linux-gnu:/code/.s/root/usr/lib64:/code/.s/root/lib:/code/.s/root/lib/x86_64-linux-gnu:/code/.s/root/python/lib/python2.7/site-packages:/code/.s/root/python/lib/python3.6/site-packages:/code:/code/lib:/usr/local/lib",
      "PATH": "/code/.s/root/usr/local/bin:/code/.s/root/usr/local/sbin:/code/.s/root/usr/bin:/code/.s/root/usr/sbin:/code/.s/root/sbin:/code/.s/root/bin:/code:/code/node_modules/.bin:/code/.s/python/bin:/code/.s/node_modules/.bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/sbin:/bin",
      "NODE_PATH": "/code/node_modules:/usr/local/lib/node_modules",
      "PYTHONUSERBASE": "/code/.s/python"
    }
     Make service fc-deploy-service success.
     Make function fc-deploy-service/event-py3 success.
    [2021-11-12T18:55:10.693] [INFO ] [FC-DEPLOY] - Checking Service fc-deploy-service exists
    [2021-11-12T18:55:10.737] [INFO ] [FC-DEPLOY] - Checking Function event-py3 exists
    
    Tips for next step
    ======================
    * Display information of the deployed resource: s info
    * Display metrics: s metrics
    * Display logs: s logs
    * Invoke remote function: s invoke
    * Remove Service: s remove service
    * Remove Function: s remove function
    * Remove Trigger: s remove trigger
    * Remove CustomDomain: s remove domain
    
    
    
    fc-deploy-test:
      region:   cn-hangzhou
      service:
        name: fc-deploy-service
      function:
        name:       event-py3
        runtime:    python3
        handler:    index.handler
        memorySize: 128
        timeout:    60
  8. Verify the result.
    View the trace in the Function Compute console. The custom span that you created is connected to the spans of Function Compute. cold-start