void profiler::install()

in src/runtime/profiler.cpp [320:520]


void profiler::install(service_spec &)
{
    s_task_code_max = dsn::task_code::max();
    s_spec_profilers.reset(new task_spec_profiler[s_task_code_max + 1]);
    task_ext_for_profiler::register_ext();
    message_ext_for_profiler::register_ext();

    for (int i = 0; i <= s_task_code_max; i++) {
        if (i == TASK_CODE_INVALID)
            continue;

        std::string name(dsn::task_code(i).to_string());
        std::string section_name = std::string("task.") + name;
        task_spec *spec = task_spec::get(i);
        CHECK_NOTNULL(spec, "");

        s_spec_profilers[i].collect_call_count = dsn_config_get_value_bool(
            section_name.c_str(),
            "collect_call_count",
            FLAGS_collect_call_count,
            "whether to collect how many time this kind of tasks invoke each of other kinds tasks");
        s_spec_profilers[i].call_counts = new std::atomic<int64_t>[ s_task_code_max + 1 ];
        std::fill(s_spec_profilers[i].call_counts,
                  s_spec_profilers[i].call_counts + s_task_code_max + 1,
                  0);

        s_spec_profilers[i].is_profile =
            dsn_config_get_value_bool(section_name.c_str(),
                                      "is_profile",
                                      FLAGS_is_profile,
                                      "whether to profile this kind of task");

        if (!s_spec_profilers[i].is_profile)
            continue;

        if (dsn_config_get_value_bool(
                section_name.c_str(),
                "profiler::inqueue",
                true,
                "whether to profile the number of this kind of tasks in all queues"))
            s_spec_profilers[i].ptr[TASK_IN_QUEUE].init_global_counter(
                "zion",
                "profiler",
                (name + std::string(".inqueue")).c_str(),
                COUNTER_TYPE_NUMBER,
                "task number in all queues");

        if (dsn_config_get_value_bool(section_name.c_str(),
                                      "profiler::queue",
                                      true,
                                      "whether to profile the queuing time of a task"))
            s_spec_profilers[i].ptr[TASK_QUEUEING_TIME_NS].init_global_counter(
                "zion",
                "profiler",
                (name + std::string(".queue(ns)")).c_str(),
                COUNTER_TYPE_NUMBER_PERCENTILES,
                "latency due to waiting in the queue");

        if (dsn_config_get_value_bool(section_name.c_str(),
                                      "profiler::exec",
                                      true,
                                      "whether to profile the executing time of a task"))
            s_spec_profilers[i].ptr[TASK_EXEC_TIME_NS].init_global_counter(
                "zion",
                "profiler",
                (name + std::string(".exec(ns)")).c_str(),
                COUNTER_TYPE_NUMBER_PERCENTILES,
                "latency due to executing tasks");

        if (dsn_config_get_value_bool(section_name.c_str(),
                                      "profiler::qps",
                                      true,
                                      "whether to profile the qps of a task"))
            s_spec_profilers[i].ptr[TASK_THROUGHPUT].init_global_counter(
                "zion",
                "profiler",
                (name + std::string(".qps")).c_str(),
                COUNTER_TYPE_RATE,
                "task numbers per second");

        if (dsn_config_get_value_bool(section_name.c_str(),
                                      "profiler::cancelled",
                                      true,
                                      "whether to profile the cancelled times of a task"))
            s_spec_profilers[i].ptr[TASK_CANCELLED].init_global_counter(
                "zion",
                "profiler",
                (name + std::string(".cancelled")).c_str(),
                COUNTER_TYPE_NUMBER,
                "cancelled times of a specific task type");

        if (spec->type == dsn_task_type_t::TASK_TYPE_RPC_REQUEST) {
            if (dsn_config_get_value_bool(section_name.c_str(),
                                          "profiler::latency.server",
                                          true,
                                          "whether to profile the server latency of a task")) {
                s_spec_profilers[i].ptr[RPC_SERVER_LATENCY_NS].init_global_counter(
                    "zion",
                    "profiler",
                    (name + std::string(".latency.server")).c_str(),
                    COUNTER_TYPE_NUMBER_PERCENTILES,
                    "latency from enqueue point to reply point on the server side for RPC "
                    "tasks");
            }
            if (dsn_config_get_value_bool(section_name.c_str(),
                                          "profiler::size.request.server",
                                          false,
                                          "whether to profile the size per request")) {
                s_spec_profilers[i].ptr[RPC_SERVER_SIZE_PER_REQUEST_IN_BYTES].init_global_counter(
                    "zion",
                    "profiler",
                    (name + std::string(".size.request.server")).c_str(),
                    COUNTER_TYPE_NUMBER_PERCENTILES,
                    "");
            }
            if (dsn_config_get_value_bool(section_name.c_str(),
                                          "profiler::size.response.server",
                                          false,
                                          "whether to profile the size per response")) {
                s_spec_profilers[i].ptr[RPC_SERVER_SIZE_PER_RESPONSE_IN_BYTES].init_global_counter(
                    "zion",
                    "profiler",
                    (name + std::string(".size.response.server")).c_str(),
                    COUNTER_TYPE_NUMBER_PERCENTILES,
                    "");
            }
            if (dsn_config_get_value_bool(
                    section_name.c_str(),
                    "rpc_request_dropped_before_execution_when_timeout",
                    false,
                    "whether to profile the number of rpc dropped for timeout"))
                s_spec_profilers[i].ptr[RPC_DROPPED_IF_TIMEOUT].init_global_counter(
                    "zion",
                    "profiler",
                    (name + std::string(".rpc.dropped")).c_str(),
                    COUNTER_TYPE_VOLATILE_NUMBER,
                    "rpc dropped if queue time exceed client timeout");
        } else if (spec->type == dsn_task_type_t::TASK_TYPE_RPC_RESPONSE) {
            if (dsn_config_get_value_bool(section_name.c_str(),
                                          "profiler::latency.client",
                                          true,
                                          "whether to profile the client latency of a task"))
                s_spec_profilers[i].ptr[RPC_CLIENT_NON_TIMEOUT_LATENCY_NS].init_global_counter(
                    "zion",
                    "profiler",
                    (name + std::string(".latency.client(ns)")).c_str(),
                    COUNTER_TYPE_NUMBER_PERCENTILES,
                    "latency from call point to enqueue point on the client side for RPC "
                    "tasks");
            if (dsn_config_get_value_bool(section_name.c_str(),
                                          "profiler::timeout.qps",
                                          true,
                                          "whether to profile the timeout qps of a task"))
                s_spec_profilers[i].ptr[RPC_CLIENT_TIMEOUT_THROUGHPUT].init_global_counter(
                    "zion",
                    "profiler",
                    (name + std::string(".timeout.qps")).c_str(),
                    COUNTER_TYPE_RATE,
                    "time-out task numbers per second for RPC tasks");
        } else if (spec->type == dsn_task_type_t::TASK_TYPE_AIO) {
            if (dsn_config_get_value_bool(section_name.c_str(),
                                          "profiler::latency",
                                          true,
                                          "whether to profile the latency of an AIO task"))
                s_spec_profilers[i].ptr[AIO_LATENCY_NS].init_global_counter(
                    "zion",
                    "profiler",
                    (name + std::string(".latency(ns)")).c_str(),
                    COUNTER_TYPE_NUMBER_PERCENTILES,
                    "latency from call point to enqueue point for AIO tasks");
        }

        // we don't use perf_counter_ptr but perf_counter* in ptr[xxx] to avoid unnecessary memory
        // access cost
        // we need to add reference so that the counters won't go
        // release_ref should be done when the profiler exits (which never happens right now so we
        // omit that for the time being)
        for (size_t j = 0; j < sizeof(s_spec_profilers[i].ptr) / sizeof(perf_counter *); j++) {
            if (s_spec_profilers[i].ptr[j].get() != nullptr) {
                s_spec_profilers[i].ptr[j]->add_ref();
            }
        }

        spec->on_task_create.put_back(profiler_on_task_create, "profiler");
        spec->on_task_enqueue.put_back(profiler_on_task_enqueue, "profiler");
        spec->on_task_begin.put_back(profiler_on_task_begin, "profiler");
        spec->on_task_end.put_back(profiler_on_task_end, "profiler");
        spec->on_task_cancelled.put_back(profiler_on_task_cancelled, "profiler");
        spec->on_task_wait_pre.put_back(profiler_on_task_wait_pre, "profiler");
        spec->on_task_wait_post.put_back(profiler_on_task_wait_post, "profiler");
        spec->on_task_cancel_post.put_back(profiler_on_task_cancel_post, "profiler");
        spec->on_aio_call.put_back(profiler_on_aio_call, "profiler");
        spec->on_aio_enqueue.put_back(profiler_on_aio_enqueue, "profiler");
        spec->on_rpc_call.put_back(profiler_on_rpc_call, "profiler");
        spec->on_rpc_request_enqueue.put_back(profiler_on_rpc_request_enqueue, "profiler");
        spec->on_rpc_task_dropped.put_back(profile_on_rpc_task_dropped, "profiler");
        spec->on_rpc_create_response.put_back(profiler_on_rpc_create_response, "profiler");
        spec->on_rpc_reply.put_back(profiler_on_rpc_reply, "profiler");
        spec->on_rpc_response_enqueue.put_back(profiler_on_rpc_response_enqueue, "profiler");
    }
}