utils/metrics.go (1,164 lines of code) (raw):

// Copyright (c) 2017-2018 Uber Technologies, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "fmt" "github.com/uber-go/tally" "strconv" "sync" ) // MetricName is the type of the metric. type MetricName int // List of supported metric names. const ( // DataNode metrics AllocatedDeviceMemory MetricName = iota AppendedRecords ArchivingCount ArchivingHighWatermark ArchivingIgnoredRecords ArchivingLowWatermark ArchivingRecords ArchivingTimingTotal BackfillAffectedDays BackfillBufferFillRatio BackfillBufferNumRecords BackfillBufferSize BackfillCount BackfillDeleteThenInsertRecords BackfillInplaceUpdateRecords BackfillLockTiming BackfillNewRecords BackfillNoEffectRecords BackfillRecords BackfillRecordsColumnRemoved BackfillRecordsRatio BackfillRecordsTimeDifference BackfillTimingTotal BatchSize BatchSizeReportTime CurrentRedologCreationTime CurrentRedologSize DuplicateRecordRatio EstimatedDeviceMemory HTTPHandlerCall HTTPHandlerLatency IngestSkippedRecords IngestedErrorBatches IngestedRecords IngestedRecoveryBatches IngestedUpsertBatches IngestionLagPerColumn IngestionWritelockAquireTime IngestionPrimaryKeyLookupTime JobFailuresCount ManagedMemorySize MemoryOverflow NumberOfEnumCasesPerColumn NumberOfRedologs PreloadingZoneEvicted PrimaryKeyMissing PurgeCount PurgeTimingTotal PurgedBatches QueryArchiveBatchProcessed QueryArchiveBytesTransferred QueryArchiveRecordsProcessed QueryBatchTransferTime QueryDimReadLatency QueryFailed QueryLatency QueryLiveBatchProcessed QueryLiveBytesTransferred QueryLiveRecordsProcessed QueryReadLockAcquireTime QueryReceived QueryRowsReturned QuerySQLParsingLatency QuerySucceeded QueryWaitForMemoryDuration RawVPBytesFetched RawVPFetchBytesPerSec RawVPFetchFailure RawVPFetchSuccess RawVPFetchTime RecordsFromFuture RecordsOutOfRetention RecoveryIgnoredRecords RecoveryIgnoredRecordsTimeDifference RecoveryLatency RecoveryUpsertBatchSize RedoLogFileCorrupt SchemaCreationCount SchemaDeletionCount SchemaFetchFailure SchemaFetchFailureEnum SchemaFetchSuccess SchemaUpdateCount SizeOfRedologs SnapshotCount SnapshotTimingBuildIndex SnapshotTimingLoad SnapshotTimingTotal TimeColumnMissing TimezoneLookupTableCreationTime TotalMemorySize TotalRawVPFetchTime UnmanagedMemorySize UpdatedRecords UpsertBatchSize // Broker metrics AQLQueryReceivedBroker SQLQueryReceivedBroker QueryFailedBroker QuerySucceededBroker QueryLatencyBroker SQLParsingLatencyBroker QueryPlanExecuteFailures DataNodeQueryFailures TimeWaitedForDataNode TimeSerDeDataNodeResponse MetricNamesSentinel ) // MetricType is the supported metric type. type MetricType int // MetricTypes which are supported. const ( Counter MetricType = iota Gauge Timer ) // metricDefinition contains the definition for a metric. type metricDefinition struct { // scope name for this definition name string // additional tags tags map[string]string // metric type metricType MetricType // cached tally counter counter tally.Counter // cached tally gauge gauge tally.Gauge // cached tally timer timer tally.Timer } // Scope names . const ( // datanode metrics scopeNameRecoveryLatency = "recovery_latency" scopeNameAllocatedDeviceMemory = "allocated_device_memory" scopeNameArchivingRecords = "archiving_records" scopeNameArchivingHighWatermark = "archiving_high_watermark" scopeNameArchivingLowWatermark = "archiving_low_watermark" scopeNameBackfillRecords = "backfill_records" scopeNameBackfillNewRecords = "backfill_new_records" scopeNameBackfillNoEffectRecords = "backfill_no_effect_records" scopeNameBackfillInplaceUpdateRecords = "backfill_inplace_records" scopeNameBackfillDeleteInsertRecords = "backfill_delete_insert_records" scopeNameBackfillAffectedDays = "backfill_affected_days" scopeNameBackfillRecordsTimeDifference = "backfill_records_time_diff" scopeNameBackfillRecordsRatio = "backfill_records_ratio_per_batch" scopeNameBackfillLockTiming = "backfill_lock_timing" scopeNameBackfillRecordsColumnRemoved = "backfill_records_column_removed" scopeNameDuplicateRecordRatio = "duplicate_record_ratio" scopeNameEstimatedDeviceMemory = "estimated_device_memory" scopeNameHTTPHandlerCall = "http.call" scopeNameHTTPHandlerLatency = "http.latency" scopeNamePrimaryKeyMissing = "primary_key_missing" scopeNameTimeColumnMissing = "time_column_missing" scopeNameIngestedRecords = "ingested_records" scopeNameAppendedRecords = "appended_records" scopeNameUpdatedRecords = "updated_records" scopeNameIngestSkippedRecords = "skipped_records" scopeNameIngestedUpsertBatches = "ingested_upsert_batches" scopeNameIngestedRecoveryBatches = "ingested_recovery_batches" scopeNameIngestedErrorBatches = "ingested_error_batches" scopeNameUpsertBatchSize = "upsert_batch_size" scopeNameRecoveryUpsertBatchSize = "recovery_upsert_batch_size" scopeNameLoad = "load" scopeNameTotal = "total" scopeNameCount = "count" scopeNameBuildIndex = "build_index" scopeNameTotalMemorySize = "total_memory_size" scopeNameUnmanagedMemorySize = "unmanaged_memory_size" scopeNameManagedMemorySize = "managed_memory_size" scopeNameBackfillBufferSize = "backfill_buffer_size" scopeNameBackfillBufferNumRecords = "backfill_buffer_num_records" scopeNameBackfillBufferFillRatio = "backfill_buffer_fill_ratio" scopeNameIngestionLagPerColumn = "ingestion_lag" scopeNameCurrentRedologCreationTime = "current_redolog_creation_time" scopeNameCurrentRedologSize = "current_redolog_size" scopeNameNumberOfRedologs = "number_of_redologs" scopeNameSizeOfRedologs = "size_of_redologs" scopeNameNumberOfEnumCasesPerColumn = "number_of_enum_cases" scopeNameQueryFailed = "query_failed" scopeNameQuerySucceeded = "query_succeeded" scopeNameQueryLatency = "query_latency" scopeNameQueryDimReadLatency = "query_dim_read_latency" scopeNameQuerySQLParsingLatency = "sql_parsing_latency" scopeNameQueryWaitForMemoryDuration = "query_wait_for_memory_duration" scopeNameQueryReceived = "query_received" scopeNameQueryRecordsProcessed = "records_processed" scopeNameBatchTransferTime = "batch_transfer_time" scopeNameQueryBatchProcessed = "batch_processed" scopeNameQueryBytesTransferred = "bytes_transferred" scopeNameQueryRowsReturned = "rows_returned" scopeNameRecordsOutOfRetention = "records_out_of_retention" scopeNameTimezoneLookupTableCreationTime = "timezone_lookup_table_creation_time" scopeNameRedoLogFileCorrupt = "redo_log_file_corrupt" scopeNameMemoryOverflow = "memory_overflow" scopeNameRawVPBytesFetched = "raw_vp_bytes_fetched" scopeNameRawVPFetchBytesPerSec = "raw_vp_fetch_bytes_per_sec" scopeNameRawVPFetchFailure = "raw_vp_fetch_failure" scopeNameRawVPFetchSuccess = "raw_vp_fetch_success" scopeNameRawVPFetchTime = "raw_vp_fetch_time" scopeNameTotalRawVPFetchTime = "total_raw_vp_fetch_time" scopeNamePreloadingZoneEvicted = "preloading_zone_evicted" scopeNameBatchesPurged = "purged_batches" scopeNameFutureRecords = "records_from_future" scopeNameBatchSize = "batch_size" scopeNameBatchSizeReportTime = "batch_size_report_time" scopeNameSchemaFetchSuccess = "schema_fetch_success" scopeNameSchemaFetchFailure = "schema_fetch_failure" scopeNameSchemaFetchFailureEnum = "schema_fetch_failure_enum" scopeNameSchemaUpdateCount = "schema_updates" scopeNameSchemaDeletionCount = "schema_deletions" scopeNameSchemaCreationCount = "schema_creations" scopeNameJobFailuresCount = "job_failures_count" scopeNameWriteLockAcquireTime = "writelock_acquire_time" scopeNameReadLockAcquireTime = "readlock_acquire_time" scopeNamePrimaryKeyLookupTime = "pk_lookup_time" // broker metrics scopeNameAQLQueryReceivedBroker = "aql_query_received_broker" scopeNameSQLQueryReceivedBroker = "sql_query_received_broker" scopeNameQueryFailedBroker = "query_failed_broker" scopeNameQuerySucceededBroker = "query_succeeded_broker" scopeNameQueryLatencyBroker = "query_latency_broker" scopeNameSQLParsingLatencyBroker = "sql_parsing_latency_broker" scopeNameQueryPlanExecuteFailures = "query_plan_execute_failures" scopeNameDataNodeQueryFailures = "datanode_query_failures" scopeNameTimeWaitedForDataNode = "time_waited_for_datanodes" scopeNameTimeSerDeDataNodeResponse = "time_serde_response" ) // Metric tag names const ( metricsTagComponent = "component" metricsTagOperation = "operation" metricsTagHandler = "handler" metricsTagStatusCode = "status_code" metricsTagOrigin = "origin" metricsTagTable = "table" metricsTagShard = "shard" metricsTagStore = "store" ) const ( metricsStoreLive = "live" metricsStoreArchive = "archive" ) // Metric component tag values const ( metricsComponentMemStore = "memstore" metricsComponentAPI = "api" metricsComponentDiskStore = "diskstore" metricsComponentMetaStore = "metastore" metricsComponentQuery = "query" metricsComponentStats = "stats" ) // Metric operation tag values const ( metricsOperationArchiving = "archiving" metricsOperationBackfill = "backfill" metricsOperationBootstrap = "bootstrap" metricsOperationIngestion = "ingestion" metricsOperationPurge = "purge" metricsOperationRecovery = "recovery" metricsOperationSnapshot = "snapshot" ) var metricDefs = map[MetricName]metricDefinition{ AllocatedDeviceMemory: { name: scopeNameAllocatedDeviceMemory, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, ArchivingIgnoredRecords: { name: scopeNameBackfillRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationArchiving, metricsTagComponent: metricsComponentMemStore, }, }, ArchivingCount: { name: scopeNameCount, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationArchiving, metricsTagComponent: metricsComponentMemStore, }, }, ArchivingRecords: { name: scopeNameArchivingRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationArchiving, metricsTagComponent: metricsComponentMemStore, }, }, ArchivingHighWatermark: { name: scopeNameArchivingHighWatermark, metricType: Gauge, tags: map[string]string{ metricsTagOperation: metricsOperationArchiving, metricsTagComponent: metricsComponentMemStore, }, }, ArchivingLowWatermark: { name: scopeNameArchivingLowWatermark, metricType: Gauge, tags: map[string]string{ metricsTagOperation: metricsOperationArchiving, metricsTagComponent: metricsComponentMemStore, }, }, ArchivingTimingTotal: { name: scopeNameTotal, metricType: Timer, tags: map[string]string{ metricsTagOperation: metricsOperationArchiving, metricsTagComponent: metricsComponentMemStore, }, }, BackfillTimingTotal: { name: scopeNameTotal, metricType: Timer, tags: map[string]string{ metricsTagOperation: metricsOperationBackfill, metricsTagComponent: metricsComponentMemStore, }, }, BackfillLockTiming: { name: scopeNameBackfillLockTiming, metricType: Timer, tags: map[string]string{ metricsTagOperation: metricsOperationBackfill, metricsTagComponent: metricsComponentMemStore, }, }, BackfillCount: { name: scopeNameCount, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationBackfill, metricsTagComponent: metricsComponentMemStore, }, }, EstimatedDeviceMemory: { name: scopeNameEstimatedDeviceMemory, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, HTTPHandlerCall: { name: scopeNameHTTPHandlerCall, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentAPI, }, }, HTTPHandlerLatency: { name: scopeNameHTTPHandlerLatency, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentAPI, }, }, IngestedRecords: { name: scopeNameIngestedRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, AppendedRecords: { name: scopeNameAppendedRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, UpdatedRecords: { name: scopeNameUpdatedRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, IngestSkippedRecords: { name: scopeNameIngestSkippedRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, IngestedUpsertBatches: { name: scopeNameIngestedUpsertBatches, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, IngestedRecoveryBatches: { name: scopeNameIngestedRecoveryBatches, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, IngestedErrorBatches: { name: scopeNameIngestedErrorBatches, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, UpsertBatchSize: { name: scopeNameUpsertBatchSize, metricType: Gauge, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, RecoveryUpsertBatchSize: { name: scopeNameRecoveryUpsertBatchSize, metricType: Gauge, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, PrimaryKeyMissing: { name: scopeNamePrimaryKeyMissing, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, TimeColumnMissing: { name: scopeNameTimeColumnMissing, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, DuplicateRecordRatio: { name: scopeNameDuplicateRecordRatio, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, }, }, BackfillRecords: { name: scopeNameBackfillRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, BackfillRecordsTimeDifference: { name: scopeNameBackfillRecordsTimeDifference, metricType: Gauge, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, BackfillRecordsRatio: { name: scopeNameBackfillRecordsRatio, metricType: Gauge, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, BackfillRecordsColumnRemoved: { name: scopeNameBackfillRecordsColumnRemoved, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, BackfillAffectedDays: { name: scopeNameBackfillAffectedDays, metricType: Gauge, tags: map[string]string{ metricsTagOperation: metricsOperationBackfill, metricsTagComponent: metricsComponentMemStore, }, }, BackfillNewRecords: { name: scopeNameBackfillNewRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationBackfill, metricsTagComponent: metricsComponentMemStore, }, }, BackfillInplaceUpdateRecords: { name: scopeNameBackfillInplaceUpdateRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationBackfill, metricsTagComponent: metricsComponentMemStore, }, }, BackfillDeleteThenInsertRecords: { name: scopeNameBackfillDeleteInsertRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationBackfill, metricsTagComponent: metricsComponentMemStore, }, }, BackfillNoEffectRecords: { name: scopeNameBackfillNoEffectRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationBackfill, metricsTagComponent: metricsComponentMemStore, }, }, RecoveryIgnoredRecords: { name: scopeNameBackfillRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationRecovery, metricsTagComponent: metricsComponentMemStore, }, }, RecoveryIgnoredRecordsTimeDifference: { name: scopeNameBackfillRecordsTimeDifference, metricType: Gauge, tags: map[string]string{ metricsTagOperation: metricsOperationRecovery, metricsTagComponent: metricsComponentMemStore, }, }, RecoveryLatency: { name: scopeNameRecoveryLatency, metricType: Timer, tags: map[string]string{ metricsTagOperation: metricsOperationRecovery, metricsTagComponent: metricsComponentMemStore, }, }, TotalMemorySize: { name: scopeNameTotalMemorySize, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, }, }, UnmanagedMemorySize: { name: scopeNameUnmanagedMemorySize, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, }, }, ManagedMemorySize: { name: scopeNameManagedMemorySize, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, }, }, BackfillBufferFillRatio: { name: scopeNameBackfillBufferFillRatio, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, }, }, BackfillBufferSize: { name: scopeNameBackfillBufferSize, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, }, }, BackfillBufferNumRecords: { name: scopeNameBackfillBufferNumRecords, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, }, }, IngestionLagPerColumn: { name: scopeNameIngestionLagPerColumn, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, }, }, IngestionWritelockAquireTime: { name: scopeNameWriteLockAcquireTime, metricType: Timer, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, IngestionPrimaryKeyLookupTime: { name: scopeNamePrimaryKeyLookupTime, metricType: Timer, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, CurrentRedologCreationTime: { name: scopeNameCurrentRedologCreationTime, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentDiskStore, }, }, CurrentRedologSize: { name: scopeNameCurrentRedologSize, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentDiskStore, }, }, NumberOfRedologs: { name: scopeNameNumberOfRedologs, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentDiskStore, }, }, SizeOfRedologs: { name: scopeNameSizeOfRedologs, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentDiskStore, }, }, NumberOfEnumCasesPerColumn: { name: scopeNameNumberOfEnumCasesPerColumn, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentMetaStore, }, }, QueryFailed: { name: scopeNameQueryFailed, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QuerySucceeded: { name: scopeNameQuerySucceeded, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QueryLatency: { name: scopeNameQueryLatency, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QuerySQLParsingLatency: { name: scopeNameQuerySQLParsingLatency, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QueryDimReadLatency: { name: scopeNameQueryDimReadLatency, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QueryWaitForMemoryDuration: { name: scopeNameQueryWaitForMemoryDuration, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QueryReadLockAcquireTime: { name: scopeNameReadLockAcquireTime, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QueryReceived: { name: scopeNameQueryReceived, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QueryLiveRecordsProcessed: { name: scopeNameQueryRecordsProcessed, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, metricsTagStore: metricsStoreLive, }, }, QueryArchiveRecordsProcessed: { name: scopeNameQueryRecordsProcessed, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, metricsTagStore: metricsStoreArchive, }, }, QueryBatchTransferTime: { name: scopeNameBatchTransferTime, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QueryLiveBatchProcessed: { name: scopeNameQueryBatchProcessed, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, metricsTagStore: metricsStoreLive, }, }, QueryArchiveBatchProcessed: { name: scopeNameQueryBatchProcessed, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, metricsTagStore: metricsStoreArchive, }, }, QueryLiveBytesTransferred: { name: scopeNameQueryBytesTransferred, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, metricsTagStore: metricsStoreLive, }, }, QueryArchiveBytesTransferred: { name: scopeNameQueryBytesTransferred, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, metricsTagStore: metricsStoreArchive, }, }, QueryRowsReturned: { name: scopeNameQueryRowsReturned, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, RecordsOutOfRetention: { name: scopeNameRecordsOutOfRetention, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, SnapshotTimingTotal: { name: scopeNameTotal, metricType: Timer, tags: map[string]string{ metricsTagOperation: metricsOperationSnapshot, metricsTagComponent: metricsComponentMemStore, }, }, SnapshotTimingLoad: { name: scopeNameLoad, metricType: Timer, tags: map[string]string{ metricsTagOperation: metricsOperationSnapshot, metricsTagComponent: metricsComponentMemStore, }, }, SnapshotTimingBuildIndex: { name: scopeNameBuildIndex, metricType: Timer, tags: map[string]string{ metricsTagOperation: metricsOperationSnapshot, metricsTagComponent: metricsComponentMemStore, }, }, SnapshotCount: { name: scopeNameCount, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationSnapshot, metricsTagComponent: metricsComponentMemStore, }, }, TimezoneLookupTableCreationTime: { name: scopeNameTimezoneLookupTableCreationTime, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, RedoLogFileCorrupt: { name: scopeNameRedoLogFileCorrupt, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentDiskStore, }, }, MemoryOverflow: { name: scopeNameMemoryOverflow, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, }, }, RawVPFetchTime: { name: scopeNameRawVPFetchTime, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, metricsTagOperation: metricsOperationBootstrap, }, }, RawVPBytesFetched: { name: scopeNameRawVPBytesFetched, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, metricsTagOperation: metricsOperationBootstrap, }, }, RawVPFetchSuccess: { name: scopeNameRawVPFetchSuccess, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, metricsTagOperation: metricsOperationBootstrap, }, }, RawVPFetchFailure: { name: scopeNameRawVPFetchFailure, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, metricsTagOperation: metricsOperationBootstrap, }, }, TotalRawVPFetchTime: { name: scopeNameTotalRawVPFetchTime, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, metricsTagOperation: metricsOperationBootstrap, }, }, RawVPFetchBytesPerSec: { name: scopeNameRawVPFetchBytesPerSec, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, metricsTagOperation: metricsOperationBootstrap, }, }, PreloadingZoneEvicted: { name: scopeNamePreloadingZoneEvicted, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentMemStore, }, }, PurgeTimingTotal: { name: scopeNameTotal, metricType: Timer, tags: map[string]string{ metricsTagOperation: metricsOperationPurge, metricsTagComponent: metricsComponentMemStore, }, }, PurgedBatches: { name: scopeNameBatchesPurged, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationPurge, metricsTagComponent: metricsComponentMemStore, }, }, RecordsFromFuture: { name: scopeNameFutureRecords, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationIngestion, metricsTagComponent: metricsComponentMemStore, }, }, BatchSize: { name: scopeNameBatchSize, metricType: Gauge, tags: map[string]string{ metricsTagComponent: metricsComponentStats, }, }, BatchSizeReportTime: { name: scopeNameBatchSizeReportTime, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentStats, }, }, SchemaFetchSuccess: { name: scopeNameSchemaFetchSuccess, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentMetaStore, }, }, SchemaFetchFailure: { name: scopeNameSchemaFetchFailure, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentMetaStore, }, }, SchemaFetchFailureEnum: { name: scopeNameSchemaFetchFailureEnum, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentMetaStore, }, }, SchemaUpdateCount: { name: scopeNameSchemaUpdateCount, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentMetaStore, }, }, SchemaDeletionCount: { name: scopeNameSchemaDeletionCount, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentMetaStore, }, }, SchemaCreationCount: { name: scopeNameSchemaCreationCount, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentMetaStore, }, }, PurgeCount: { name: scopeNameCount, metricType: Counter, tags: map[string]string{ metricsTagOperation: metricsOperationPurge, metricsTagComponent: metricsComponentMemStore, }, }, JobFailuresCount: { name: scopeNameJobFailuresCount, metricType: Counter, tags: map[string]string{}, }, AQLQueryReceivedBroker: { name: scopeNameAQLQueryReceivedBroker, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, SQLQueryReceivedBroker: { name: scopeNameSQLQueryReceivedBroker, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QueryFailedBroker: { name: scopeNameQueryFailedBroker, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QuerySucceededBroker: { name: scopeNameQuerySucceededBroker, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QueryLatencyBroker: { name: scopeNameQueryLatencyBroker, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, SQLParsingLatencyBroker: { name: scopeNameSQLParsingLatencyBroker, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, QueryPlanExecuteFailures: { name: scopeNameQueryPlanExecuteFailures, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, DataNodeQueryFailures: { name: scopeNameDataNodeQueryFailures, metricType: Counter, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, TimeWaitedForDataNode: { name: scopeNameTimeWaitedForDataNode, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, TimeSerDeDataNodeResponse: { name: scopeNameTimeSerDeDataNodeResponse, metricType: Timer, tags: map[string]string{ metricsTagComponent: metricsComponentQuery, }, }, } func (def *metricDefinition) init(rootScope tally.Scope) { switch def.metricType { case Counter: def.counter = rootScope.Tagged(def.tags).Counter(def.name) case Gauge: def.gauge = rootScope.Tagged(def.tags).Gauge(def.name) case Timer: def.timer = rootScope.Tagged(def.tags).Timer(def.name) } } // ReporterFactory manages reporters for different table and shards. // If the corresponding metrics are not associated with any table // or shard. It can use the root reporter. type ReporterFactory struct { sync.RWMutex rootReporter *Reporter reporters map[string]*Reporter } // NewReporterFactory returns a new report factory. func NewReporterFactory(rootScope tally.Scope) *ReporterFactory { return &ReporterFactory{ rootReporter: NewReporter(rootScope), reporters: make(map[string]*Reporter), } } // AddTableShard adds a reporter for the given table and shards. It should // be called when bootstrap the table shards or shard ownership changes. func (f *ReporterFactory) AddTableShard(tableName string, shardID int) { f.Lock() defer f.Unlock() key := fmt.Sprintf("%s_%d", tableName, shardID) _, ok := f.reporters[key] if !ok { f.reporters[key] = NewReporter(f.rootReporter.GetRootScope().Tagged(map[string]string{ metricsTagTable: tableName, metricsTagShard: strconv.Itoa(shardID), })) } } // DeleteTableShard deletes the reporter for the given table and shards. It should // be called when the table shard no longer belongs to current node. func (f *ReporterFactory) DeleteTableShard(tableName string, shardID int) { f.Lock() defer f.Unlock() key := fmt.Sprintf("%s_%d", tableName, shardID) delete(f.reporters, key) } // GetReporter returns reporter given tableName and shardID. If the corresponding // reporter cannot be found. It will return the root scope. func (f *ReporterFactory) GetReporter(tableName string, shardID int) *Reporter { f.RLock() defer f.RUnlock() key := fmt.Sprintf("%s_%d", tableName, shardID) reporter, ok := f.reporters[key] if ok { return reporter } return f.rootReporter } // GetRootReporter returns the root reporter. func (f *ReporterFactory) GetRootReporter() *Reporter { return f.rootReporter } // Reporter is the the interface used to report stats, type Reporter struct { rootScope tally.Scope cachedDefinitions []metricDefinition } // NewReporter returns a new reporter with supplied root scope. func NewReporter(rootScope tally.Scope) *Reporter { defs := make([]metricDefinition, int(MetricNamesSentinel)) for key, metricDefinition := range metricDefs { metricDefinition.init(rootScope) defs[key] = metricDefinition } return &Reporter{rootScope: rootScope, cachedDefinitions: defs} } // GetCounter returns the tally counter with corresponding tags. func (r *Reporter) GetCounter(n MetricName) tally.Counter { def := r.cachedDefinitions[n] if def.metricType == Counter { return def.counter } GetLogger().Panicf("Cannot get counter given %d", n) return nil } // GetGauge returns the tally gauge with corresponding tags. func (r *Reporter) GetGauge(n MetricName) tally.Gauge { def := r.cachedDefinitions[n] if def.metricType == Gauge { return def.gauge } GetLogger().Panicf("Cannot get gauge given %d", n) return nil } // GetTimer returns the tally timer with corresponding tags. func (r *Reporter) GetTimer(n MetricName) tally.Timer { def := r.cachedDefinitions[n] if def.metricType == Timer { return def.timer } GetLogger().Panicf("Cannot get timer given %d", n) return nil } // GetChildCounter create tagged child counter from reporter func (r *Reporter) GetChildCounter(tags map[string]string, n MetricName) tally.Counter { childScope := r.rootScope.Tagged(tags) def := r.cachedDefinitions[n] if def.metricType == Counter { return childScope.Tagged(def.tags).Counter(def.name) } GetLogger().Panicf("Cannot get child counter given %d", n) return nil } // GetChildGauge create tagged child gauge from reporter func (r *Reporter) GetChildGauge(tags map[string]string, n MetricName) tally.Gauge { childScope := r.rootScope.Tagged(tags) def := r.cachedDefinitions[n] if def.metricType == Gauge { return childScope.Tagged(def.tags).Gauge(def.name) } GetLogger().Panicf("Cannot get child gauge given %d", n) return nil } // GetChildTimer create tagged child timer from reporter func (r *Reporter) GetChildTimer(tags map[string]string, n MetricName) tally.Timer { childScope := r.rootScope.Tagged(tags) def := r.cachedDefinitions[n] if def.metricType == Timer { return childScope.Tagged(def.tags).Timer(def.name) } GetLogger().Panicf("Cannot get child timer given %d", n) return nil } // GetRootScope returns the root scope wrapped by this reporter. func (r *Reporter) GetRootScope() tally.Scope { return r.rootScope }