// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.
// Modifications Copyright 2022 PingCAP, Inc.

use lazy_static::lazy_static;
use prometheus::*;
use prometheus_static_metric::*;

make_static_metric! {
    pub label_enum MvccConflictKind {
        prewrite_write_conflict,
        rolled_back,
        commit_lock_not_found,
        rollback_committed,
        acquire_pessimistic_lock_conflict,
        pipelined_acquire_pessimistic_lock_amend_fail,
        pipelined_acquire_pessimistic_lock_amend_success,
    }

    pub label_enum MvccDuplicateCommandKind {
        prewrite,
        commit,
        rollback,
        acquire_pessimistic_lock,
    }

    pub label_enum MvccCheckTxnStatusKind {
        rollback,
        update_ts,
        get_commit_info,
        pessimistic_rollback,
    }

    pub label_enum MvccPrewriteAssertionPerfKind {
        none,
        write_loaded,
        write_not_loaded_reload,
        write_not_loaded_skip
    }

    pub label_enum CommitCommandKind {
        normal,
        txn_file,
    }

    pub label_enum ExtraCfScanModeKind {
        legacy,
        pruned,
        both,
    }

    pub label_enum ExtraCfScanStrategyKind {
        unified,
        two_step,
    }

    pub label_enum ExtraCfConflictOutcomeKind {
        self_rollback,
        write_conflict,
        no_conflict,
    }

    pub struct MvccConflictCounterVec: IntCounter {
        "type" => MvccConflictKind,
    }

    pub struct MvccDuplicateCmdCounterVec: IntCounter {
        "type" => MvccDuplicateCommandKind,
    }

    pub struct MvccCheckTxnStatusCounterVec: IntCounter {
        "type" => MvccCheckTxnStatusKind,
    }

    pub struct MvccPrewriteAssertionPerfCounterVec: IntCounter {
        "type" => MvccPrewriteAssertionPerfKind,
    }

    pub struct MvccCommitRejectByBackupTsCounterVec: IntCounter {
        "type" => CommitCommandKind,
    }

    pub struct MvccPrewriteRequestAfterCommitCounterVec: IntCounter {
        "type" => {
            non_retry_req,
            retry_req,
        },
    }

    pub struct ExtraCfScanExaminedEntriesVec: Histogram {
        "mode" => ExtraCfScanModeKind,
    }

    pub struct ExtraCfConflictCheckCounterVec: IntCounter {
        "mode" => ExtraCfScanModeKind,
        "strategy" => ExtraCfScanStrategyKind,
        "outcome" => ExtraCfConflictOutcomeKind,
    }

    pub struct ExtraCfPruningDatasetsCounterVec: IntCounter {
        "phase" => {
            candidate,
            filtered,
            selected,
        },
        "source" => {
            memtable,
            l0,
            stable,
        },
    }
}

lazy_static! {
    pub static ref MVCC_VERSIONS_HISTOGRAM: HistogramVec = register_histogram_vec!(
        "tikv_storage_mvcc_versions",
        "Histogram of versions for each key",
        &["key_mode"],
        exponential_buckets(1.0, 2.0, 30).unwrap()
    )
    .unwrap();
    pub static ref GC_DELETE_VERSIONS_HISTOGRAM: HistogramVec = register_histogram_vec!(
        "tikv_storage_mvcc_gc_delete_versions",
        "Histogram of versions deleted by gc for each key",
        &["key_mode"],
        exponential_buckets(1.0, 2.0, 30).unwrap()
    )
    .unwrap();
    pub static ref MVCC_CONFLICT_COUNTER: MvccConflictCounterVec = {
        register_static_int_counter_vec!(
            MvccConflictCounterVec,
            "tikv_storage_mvcc_conflict_counter",
            "Total number of conflict error",
            &["type"]
        )
        .unwrap()
    };
    pub static ref MVCC_DUPLICATE_CMD_COUNTER_VEC: MvccDuplicateCmdCounterVec = {
        register_static_int_counter_vec!(
            MvccDuplicateCmdCounterVec,
            "tikv_storage_mvcc_duplicate_cmd_counter",
            "Total number of duplicated commands",
            &["type"]
        )
        .unwrap()
    };
    pub static ref MVCC_CHECK_TXN_STATUS_COUNTER_VEC: MvccCheckTxnStatusCounterVec = {
        register_static_int_counter_vec!(
            MvccCheckTxnStatusCounterVec,
            "tikv_storage_mvcc_check_txn_status",
            "Counter of different results of check_txn_status",
            &["type"]
        )
        .unwrap()
    };
    pub static ref MVCC_PREWRITE_ASSERTION_PERF_COUNTER_VEC: MvccPrewriteAssertionPerfCounterVec = {
        register_static_int_counter_vec!(
            MvccPrewriteAssertionPerfCounterVec,
            "tikv_storage_mvcc_prewrite_assertion_perf",
            "Counter of assertion operations in transactions",
            &["type"]
        )
        .unwrap()
    };
    pub static ref EXTRA_CF_SCAN_EXAMINED_ENTRIES: ExtraCfScanExaminedEntriesVec =
        register_static_histogram_vec!(
            ExtraCfScanExaminedEntriesVec,
            "tikv_storage_extra_cf_scan_iterations",
            "Number of EXTRA_CF entries examined during conflict checks",
            &["mode"],
            exponential_buckets(1.0, 2.0, 25).unwrap()
        )
        .unwrap();
    pub static ref EXTRA_CF_CONFLICT_CHECK_COUNTER: ExtraCfConflictCheckCounterVec =
        register_static_int_counter_vec!(
            ExtraCfConflictCheckCounterVec,
            "tikv_storage_extra_cf_conflict_check_total",
            "Total EXTRA_CF conflict checks by scan mode, strategy and outcome",
            &["mode", "strategy", "outcome"]
        )
        .unwrap();
    pub static ref EXTRA_CF_PRUNING_DATASETS_COUNTER: ExtraCfPruningDatasetsCounterVec =
        register_static_int_counter_vec!(
            ExtraCfPruningDatasetsCounterVec,
            "tikv_storage_extra_cf_pruning_datasets_total",
            "Total EXTRA_CF datasets counted by pruning phase and source in pruned mode",
            &["phase", "source"]
        )
        .unwrap();
    pub static ref MVCC_COMMIT_REJECT_BY_BACKUP_TS_COUNTER_VEC: MvccCommitRejectByBackupTsCounterVec = {
        register_static_int_counter_vec!(
            MvccCommitRejectByBackupTsCounterVec,
            "tikv_storage_mvcc_commit_reject_by_backup_ts",
            "Counter of commit commands rejected by backup_ts",
            &["type"]
        )
        .unwrap()
    };
    pub static ref MVCC_PREWRITE_REQUEST_AFTER_COMMIT_COUNTER_VEC: MvccPrewriteRequestAfterCommitCounterVec = {
        register_static_int_counter_vec!(
            MvccPrewriteRequestAfterCommitCounterVec,
            "tikv_storage_mvcc_prewrite_request_after_commit_counter",
            "Counter of prewrite requests of already-committed transactions that are determined by checking TxnStatusCache",
            &["type"]
        )
        .unwrap()
    };
}
