MSSQL Metrics (Part II). (#18689)
thiagoftsm committed
Oct 9, 2024 at 15:16 UTC
30b532952ac89db2bae650baedce153ff7dcffc4
2 files changed
+754
-26
src/collectors/windows.plugin/perflib-mssql.c
+737
-26
@@ -15,7 +15,6 @@ enum netdata_mssql_metrics {
15
NETDATA_MSSQL_MEMORY,
16
NETDATA_MSSQL_BUFFER_MANAGEMENT,
17
NETDATA_MSSQL_SQL_STATS,
18
- NETDATA_MSSQL_TRANSACTIONS,
18
NETDATA_MSSQL_ACCESS_METHODS,
19
20
NETDATA_MSSQL_METRICS_END
@@ -66,6 +65,30 @@ struct mssql_instance {
65
RRDSET *st_sql_errors;
66
RRDDIM *rd_sql_errors;
67
68
+ RRDSET *st_lockWait;
69
+ RRDSET *st_deadLocks;
70
+ DICTIONARY *locks_instances;
71
+
72
+ RRDSET *st_db_data_file_size;
73
+ RRDSET *st_db_active_transactions;
74
+ RRDSET *st_db_backup_restore_operations;
75
+ RRDSET *st_db_log_flushed;
76
+ RRDSET *st_db_log_flushes;
77
+ RRDSET *st_db_transactions;
78
+ RRDSET *st_db_write_transactions;
79
+ DICTIONARY *databases;
80
+
81
+ RRDSET *st_conn_memory;
82
+ RRDDIM *rd_conn_memory;
83
+
84
+ RRDSET *st_ext_benefit_mem;
85
+ RRDDIM *rd_ext_benefit_mem;
86
+
87
+ RRDSET *st_pending_mem_grant;
88
+ RRDDIM *rd_pending_mem_grant;
89
+
90
+ RRDSET *st_mem_tot_server;
91
+ RRDDIM *rd_mem_tot_server;
92
93
COUNTER_DATA MSSQLAccessMethodPageSplits;
94
COUNTER_DATA MSSQLBufferCacheHits;
@@ -75,8 +98,6 @@ struct mssql_instance {
98
COUNTER_DATA MSSQLBufferPageWrites;
99
COUNTER_DATA MSSQLBlockedProcesses;
100
COUNTER_DATA MSSQLUserConnections;
78
- COUNTER_DATA MSSQLLockWait;
79
- COUNTER_DATA MSSQLDeadlocks;
101
COUNTER_DATA MSSQLConnectionMemoryBytes;
102
COUNTER_DATA MSSQLExternalBenefitOfMemory;
103
COUNTER_DATA MSSQLPendingMemoryGrants;
@@ -87,6 +108,20 @@ struct mssql_instance {
108
COUNTER_DATA MSSQLStatSafeAutoParameterization;
109
COUNTER_DATA MSSQLCompilations;
110
COUNTER_DATA MSSQLRecompilations;
111
+};
112
+
113
+struct mssql_lock_instance {
114
+ struct mssql_instance *parent;
115
+
116
+ COUNTER_DATA lockWait;
117
+ COUNTER_DATA deadLocks;
118
+
119
+ RRDDIM *rd_lockWait;
120
+ RRDDIM *rd_deadLocks;
121
+};
122
+
123
+struct mssql_db_instance {
124
+ struct mssql_instance *parent;
125
126
COUNTER_DATA MSSQLDatabaseActiveTransactions;
127
COUNTER_DATA MSSQLDatabaseBackupRestoreOperations;
@@ -95,6 +130,14 @@ struct mssql_instance {
130
COUNTER_DATA MSSQLDatabaseLogFlushes;
131
COUNTER_DATA MSSQLDatabaseTransactions;
132
COUNTER_DATA MSSQLDatabaseWriteTransactions;
133
+
134
+ RRDDIM *rd_db_data_file_size;
135
+ RRDDIM *rd_db_active_transactions;
136
+ RRDDIM *rd_db_backup_restore_operations;
137
+ RRDDIM *rd_db_log_flushed;
138
+ RRDDIM *rd_db_log_flushes;
139
+ RRDDIM *rd_db_transactions;
140
+ RRDDIM *rd_db_write_transactions;
141
};
142
143
static DICTIONARY *mssql_instances = NULL;
@@ -118,9 +161,6 @@ static void initialize_mssql_objects(struct mssql_instance *p, const char *insta
161
strncpyz(&name[length], "Databases", sizeof(name) - length);
162
p->objectName[NETDATA_MSSQL_DATABASE] = strdup(name);
163
121
- strncpyz(&name[length], "Transactions", sizeof(name) - length);
122
- p->objectName[NETDATA_MSSQL_TRANSACTIONS] = strdup(name);
123
-
164
strncpyz(&name[length], "SQL Statistics", sizeof(name) - length);
165
p->objectName[NETDATA_MSSQL_SQL_STATS] = strdup(name);
166
@@ -165,28 +205,49 @@ static inline void initialize_mssql_keys(struct mssql_instance *p) {
205
// Errors
206
p->MSSQLSQLErrorsTotal.key = "Errors/sec";
207
168
- /*
169
- p->MSSQLLockWait.key = "";
170
- p->MSSQLDeadlocks.key = "";
171
- p->MSSQLConnectionMemoryBytes.key = "";
172
- p->MSSQLExternalBenefitOfMemory.key = "";
173
- p->MSSQLPendingMemoryGrants.key = "";
174
- p->MSSQLTotalServerMemory.key = "";
175
-
176
- p->MSSQLDatabaseActiveTransactions.key = "";
177
- p->MSSQLDatabaseBackupRestoreOperations.key = "";
178
- p->MSSQLDatabaseDataFileSize.key = "";
179
- p->MSSQLDatabaseLogFlushed.key = "";
180
- p->MSSQLDatabaseLogFlushes.key = "";
181
- p->MSSQLDatabaseTransactions.key = "";
182
- p->MSSQLDatabaseWriteTransactions.key = "";
183
- */
208
+ p->MSSQLConnectionMemoryBytes.key = "Connection Memory (KB)";
209
+ p->MSSQLExternalBenefitOfMemory.key = "External benefit of memory";
210
+ p->MSSQLPendingMemoryGrants.key = "Memory Grants Pending";
211
+ p->MSSQLTotalServerMemory.key = "Total Server Memory (KB)";
212
+}
213
+
214
+void dict_mssql_insert_locks_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
215
+ struct mssql_lock_instance *ptr = value;
216
+ ptr->deadLocks.key = "Number of Deadlocks/sec";
217
+ ptr->lockWait.key = "Lock Waits/sec";
218
+}
219
+
220
+void dict_mssql_insert_databases_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
221
+ struct mssql_db_instance *ptr = value;
222
+
223
+ ptr->MSSQLDatabaseDataFileSize.key = "Data File(s) Size (KB)";
224
+
225
+ ptr->MSSQLDatabaseActiveTransactions.key = "Active Transactions";
226
+ ptr->MSSQLDatabaseBackupRestoreOperations.key = "Backup/Restore Throughput/sec";
227
+ ptr->MSSQLDatabaseLogFlushed.key = "Log Bytes Flushed/sec";
228
+ ptr->MSSQLDatabaseLogFlushes.key = "Log Flushes/sec";
229
+ ptr->MSSQLDatabaseTransactions.key = "Transactions/sec";
230
+ ptr->MSSQLDatabaseWriteTransactions.key = "Write Transactions/sec";
231
}
232
233
void dict_mssql_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
234
struct mssql_instance *p = value;
235
const char *instance = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
236
237
+ if (!p->locks_instances) {
238
+ p->locks_instances = dictionary_create_advanced(DICT_OPTION_DONT_OVERWRITE_VALUE |
239
+ DICT_OPTION_FIXED_SIZE,
240
+ NULL, sizeof(struct mssql_lock_instance));
241
+ dictionary_register_insert_callback(p->locks_instances, dict_mssql_insert_locks_cb, NULL);
242
+ }
243
+
244
+ if (!p->databases) {
245
+ p->databases = dictionary_create_advanced(DICT_OPTION_DONT_OVERWRITE_VALUE |
246
+ DICT_OPTION_FIXED_SIZE,
247
+ NULL, sizeof(struct mssql_db_instance));
248
+ dictionary_register_insert_callback(p->databases, dict_mssql_insert_databases_cb, NULL);
249
+ }
250
+
251
initialize_mssql_objects(p, instance);
252
initialize_mssql_keys(p);
253
}
@@ -554,7 +615,7 @@ static void do_mssql_buffer_management(PERF_DATA_BLOCK *pDataBlock, struct mssql
615
snprintfz(id, RRD_ID_LENGTH_MAX, "mssql_instance_%s_bufman_checkpoint_pages", p->instanceID);
616
p->rd_buff_checkpoint_pages = rrddim_add(p->st_buff_checkpoint_pages,
617
id,
557
- "flushed",
618
+ "log",
619
1,
620
1,
621
RRD_ALGORITHM_INCREMENTAL);
@@ -703,7 +764,7 @@ static void do_mssql_errors(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *
764
, id, NULL
765
, "Errors"
766
, "mssql.instance_sql_errors"
706
- , "Errors"
767
+ , "errors"
768
, "errors/s"
769
, PLUGIN_WINDOWS_NAME
770
, "PerflibMSSQL"
@@ -730,6 +791,655 @@ static void do_mssql_errors(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *
791
}
792
}
793
794
+int dict_mssql_locks_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
795
+ char id[RRD_ID_LENGTH_MAX + 1];
796
+ struct mssql_lock_instance *mli = value;
797
+ const char *instance = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
798
+
799
+ int *update_every = data;
800
+
801
+ if (!mli->parent->st_lockWait) {
802
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_locks_lock_wait", mli->parent->instanceID);
803
+ mli->parent->st_lockWait = rrdset_create_localhost("mssql"
804
+ , id, NULL
805
+ , "locks"
806
+ , "mssql.instance_locks_lock_wait"
807
+ , "Lock requests that required the caller to wait."
808
+ , "locks/s"
809
+ , PLUGIN_WINDOWS_NAME
810
+ , "PerflibMSSQL"
811
+ , PRIO_MSSQL_LOCKS_WAIT
812
+ , *update_every
813
+ , RRDSET_TYPE_LINE
814
+ );
815
+
816
+ rrdlabels_add(mli->parent->st_lockWait->rrdlabels, "mssql_instance", instance, RRDLABEL_SRC_AUTO);
817
+ }
818
+
819
+ if (!mli->rd_lockWait) {
820
+ snprintfz(id,
821
+ RRD_ID_LENGTH_MAX,
822
+ "mssql_instance_%s_resource_%s_locks_lock_wait_seconds",
823
+ mli->parent->instanceID,
824
+ instance);
825
+
826
+ mli->rd_lockWait = rrddim_add(mli->parent->st_lockWait,
827
+ id,
828
+ instance,
829
+ 1,
830
+ 1,
831
+ RRD_ALGORITHM_INCREMENTAL);
832
+ }
833
+
834
+ rrddim_set_by_pointer(mli->parent->st_lockWait,
835
+ mli->rd_lockWait,
836
+ (collected_number)mli->lockWait.current.Data);
837
+
838
+ if (!mli->parent->st_deadLocks) {
839
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_locks_deadlocks", mli->parent->instanceID);
840
+ mli->parent->st_deadLocks = rrdset_create_localhost("mssql"
841
+ , id, NULL
842
+ , "locks"
843
+ , "mssql.instance_locks_deadlocks"
844
+ , "Lock requests that resulted in deadlock."
845
+ , "locks/s"
846
+ , PLUGIN_WINDOWS_NAME
847
+ , "PerflibMSSQL"
848
+ , PRIO_MSSQL_LOCKS_DEADLOCK
849
+ , *update_every
850
+ , RRDSET_TYPE_LINE
851
+ );
852
+ rrdlabels_add(mli->parent->st_deadLocks->rrdlabels, "mssql_instance", instance, RRDLABEL_SRC_AUTO);
853
+ }
854
+
855
+ if (!mli->rd_deadLocks) {
856
+ snprintfz(id,
857
+ RRD_ID_LENGTH_MAX,
858
+ "mssql_instance_%s_resource_%s_locks_deadlocks",
859
+ mli->parent->instanceID,
860
+ instance);
861
+
862
+ mli->rd_deadLocks = rrddim_add(mli->parent->st_deadLocks,
863
+ id,
864
+ instance,
865
+ 1,
866
+ 1,
867
+ RRD_ALGORITHM_INCREMENTAL);
868
+ }
869
+
870
+ rrddim_set_by_pointer(mli->parent->st_deadLocks,
871
+ mli->rd_deadLocks,
872
+ (collected_number)mli->deadLocks.current.Data);
873
+}
874
+
875
+static void do_mssql_locks(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p, int update_every)
876
+{
877
+ char id[RRD_ID_LENGTH_MAX + 1];
878
+ PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, p->objectName[NETDATA_MSSQL_LOCKS]);
879
+ if (!pObjectType) return;
880
+
881
+ PERF_INSTANCE_DEFINITION *pi = NULL;
882
+ for(LONG i = 0; i < pObjectType->NumInstances ; i++) {
883
+ pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
884
+ if(!pi) break;
885
+
886
+ if(!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
887
+ strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
888
+
889
+ if(!strcasecmp(windows_shared_buffer, "_Total"))
890
+ continue;
891
+
892
+ netdata_fix_chart_name(windows_shared_buffer);
893
+ struct mssql_lock_instance *mli = dictionary_set(p->locks_instances,
894
+ windows_shared_buffer,
895
+ NULL,
896
+ sizeof(*mli));
897
+ if (!mli)
898
+ continue;
899
+
900
+ if (!mli->parent) {
901
+ mli->parent = p;
902
+ }
903
+
904
+ perflibGetObjectCounter(pDataBlock, pObjectType, &mli->lockWait);
905
+ perflibGetObjectCounter(pDataBlock, pObjectType, &mli->deadLocks);
906
+ }
907
+
908
+ dictionary_sorted_walkthrough_read(p->locks_instances, dict_mssql_locks_charts_cb, &update_every);
909
+ rrdset_done(p->st_lockWait);
910
+ rrdset_done(p->st_deadLocks);
911
+}
912
+
913
+static void mssql_database_backup_restore_chart(struct mssql_db_instance *mli, const char *db, int update_every)
914
+{
915
+ char id[RRD_ID_LENGTH_MAX + 1];
916
+ if (!mli->parent->st_db_backup_restore_operations) {
917
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_backup_restore_operations", db, mli->parent->instanceID);
918
+ mli->parent->st_db_backup_restore_operations = rrdset_create_localhost("mssql",
919
+ id,
920
+ NULL,
921
+ "transactions",
922
+ "mssql.database_backup_restore_operations",
923
+ "Backup IO per database",
924
+ "operations/s",
925
+ PLUGIN_WINDOWS_NAME,
926
+ "PerflibMSSQL",
927
+ PRIO_MSSQL_DATABASE_BACKUP_RESTORE_OPERATIONS,
928
+ update_every,
929
+ RRDSET_TYPE_LINE);
930
+
931
+ rrdlabels_add(mli->parent->st_db_backup_restore_operations->rrdlabels,
932
+ "mssql_instance",
933
+ mli->parent->instanceID,
934
+ RRDLABEL_SRC_AUTO);
935
+
936
+ rrdlabels_add(mli->parent->st_db_backup_restore_operations->rrdlabels,
937
+ "database",
938
+ db,
939
+ RRDLABEL_SRC_AUTO);
940
+ }
941
+
942
+ if (!mli->rd_db_backup_restore_operations) {
943
+ snprintfz(id,
944
+ RRD_ID_LENGTH_MAX,
945
+ "mssql_db_%s_instance_%s_backup_restore_operations",
946
+ db,
947
+ mli->parent->instanceID);
948
+
949
+ mli->rd_db_backup_restore_operations = rrddim_add(mli->parent->st_db_backup_restore_operations, id, db,
950
+ 1, 1, RRD_ALGORITHM_INCREMENTAL);
951
+ }
952
+
953
+ rrddim_set_by_pointer(mli->parent->st_db_backup_restore_operations,
954
+ mli->rd_db_backup_restore_operations,
955
+ (collected_number)mli->MSSQLDatabaseBackupRestoreOperations.current.Data);
956
+}
957
+
958
+static void mssql_database_log_flushes_chart(struct mssql_db_instance *mli, const char *db, int update_every)
959
+{
960
+ char id[RRD_ID_LENGTH_MAX + 1];
961
+ if (!mli->parent->st_db_log_flushes) {
962
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_log_flushes", db, mli->parent->instanceID);
963
+ mli->parent->st_db_log_flushes = rrdset_create_localhost("mssql",
964
+ id,
965
+ NULL,
966
+ "transactions",
967
+ "mssql.database_log_flushes",
968
+ "Log flushes",
969
+ "flushes/s",
970
+ PLUGIN_WINDOWS_NAME,
971
+ "PerflibMSSQL",
972
+ PRIO_MSSQL_DATABASE_LOG_FLUSHES,
973
+ update_every,
974
+ RRDSET_TYPE_LINE);
975
+
976
+ rrdlabels_add(mli->parent->st_db_log_flushes->rrdlabels,
977
+ "mssql_instance",
978
+ mli->parent->instanceID,
979
+ RRDLABEL_SRC_AUTO);
980
+
981
+ rrdlabels_add(mli->parent->st_db_log_flushes->rrdlabels,
982
+ "database",
983
+ db,
984
+ RRDLABEL_SRC_AUTO);
985
+ }
986
+
987
+ if (!mli->rd_db_log_flushes) {
988
+ snprintfz(id,
989
+ RRD_ID_LENGTH_MAX,
990
+ "mssql_db_%s_instance_%s_log_flushes_bytes",
991
+ db,
992
+ mli->parent->instanceID);
993
+
994
+ mli->rd_db_log_flushes = rrddim_add(mli->parent->st_db_log_flushes, id, db,
995
+ 1, 1, RRD_ALGORITHM_INCREMENTAL);
996
+ }
997
+
998
+ rrddim_set_by_pointer(mli->parent->st_db_log_flushes,
999
+ mli->rd_db_log_flushes,
1000
+ (collected_number)mli->MSSQLDatabaseLogFlushes.current.Data);
1001
+}
1002
+
1003
+static void mssql_database_log_flushed_chart(struct mssql_db_instance *mli, const char *db, int update_every)
1004
+{
1005
+ char id[RRD_ID_LENGTH_MAX + 1];
1006
+ if (!mli->parent->st_db_log_flushed) {
1007
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_log_flushed", db, mli->parent->instanceID);
1008
+ mli->parent->st_db_log_flushed = rrdset_create_localhost("mssql",
1009
+ id,
1010
+ NULL,
1011
+ "transactions",
1012
+ "mssql.database_log_flushed",
1013
+ "Log flushed",
1014
+ "bytes/s",
1015
+ PLUGIN_WINDOWS_NAME,
1016
+ "PerflibMSSQL",
1017
+ PRIO_MSSQL_DATABASE_LOG_FLUSHED,
1018
+ update_every,
1019
+ RRDSET_TYPE_LINE);
1020
+
1021
+ rrdlabels_add(mli->parent->st_db_log_flushed->rrdlabels,
1022
+ "mssql_instance",
1023
+ mli->parent->instanceID,
1024
+ RRDLABEL_SRC_AUTO);
1025
+
1026
+ rrdlabels_add(mli->parent->st_db_log_flushed->rrdlabels,
1027
+ "database",
1028
+ db,
1029
+ RRDLABEL_SRC_AUTO);
1030
+ }
1031
+
1032
+ if (!mli->rd_db_log_flushed) {
1033
+ snprintfz(id,
1034
+ RRD_ID_LENGTH_MAX,
1035
+ "mssql_db_%s_instance_%s_log_flushed_bytes",
1036
+ db,
1037
+ mli->parent->instanceID);
1038
+
1039
+ mli->rd_db_log_flushed = rrddim_add(mli->parent->st_db_log_flushed, id, db,
1040
+ 1, 1, RRD_ALGORITHM_INCREMENTAL);
1041
+ }
1042
+
1043
+ rrddim_set_by_pointer(mli->parent->st_db_log_flushed,
1044
+ mli->rd_db_log_flushed,
1045
+ (collected_number)mli->MSSQLDatabaseLogFlushed.current.Data);
1046
+}
1047
+
1048
+static void mssql_transactions_chart(struct mssql_db_instance *mli, const char *db, int update_every)
1049
+{
1050
+ char id[RRD_ID_LENGTH_MAX + 1];
1051
+ if (!mli->parent->st_db_transactions) {
1052
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_transactions", db, mli->parent->instanceID);
1053
+ mli->parent->st_db_transactions = rrdset_create_localhost("mssql",
1054
+ id,
1055
+ NULL,
1056
+ "transactions",
1057
+ "mssql.database_transactions",
1058
+ "Transactions",
1059
+ "transactions/s",
1060
+ PLUGIN_WINDOWS_NAME,
1061
+ "PerflibMSSQL",
1062
+ PRIO_MSSQL_DATABASE_TRANSACTIONS,
1063
+ update_every,
1064
+ RRDSET_TYPE_LINE);
1065
+
1066
+ rrdlabels_add(mli->parent->st_db_transactions->rrdlabels,
1067
+ "mssql_instance",
1068
+ mli->parent->instanceID,
1069
+ RRDLABEL_SRC_AUTO);
1070
+
1071
+ rrdlabels_add(mli->parent->st_db_transactions->rrdlabels,
1072
+ "database",
1073
+ db,
1074
+ RRDLABEL_SRC_AUTO);
1075
+ }
1076
+
1077
+ if (!mli->rd_db_transactions) {
1078
+ snprintfz(id,
1079
+ RRD_ID_LENGTH_MAX,
1080
+ "mssql_db_%s_instance_%s_transactions",
1081
+ db,
1082
+ mli->parent->instanceID);
1083
+
1084
+ mli->rd_db_transactions = rrddim_add(mli->parent->st_db_transactions, id, db,
1085
+ 1, 1, RRD_ALGORITHM_INCREMENTAL);
1086
+ }
1087
+
1088
+ rrddim_set_by_pointer(mli->parent->st_db_transactions,
1089
+ mli->rd_db_transactions,
1090
+ (collected_number)mli->MSSQLDatabaseTransactions.current.Data);
1091
+}
1092
+
1093
+static void mssql_write_transactions_chart(struct mssql_db_instance *mli, const char *db, int update_every)
1094
+{
1095
+ char id[RRD_ID_LENGTH_MAX + 1];
1096
+ if (!mli->parent->st_db_write_transactions) {
1097
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_write_transactions", db, mli->parent->instanceID);
1098
+ mli->parent->st_db_write_transactions = rrdset_create_localhost("mssql",
1099
+ id,
1100
+ NULL,
1101
+ "transactions",
1102
+ "mssql.database_write_transactions",
1103
+ "Write transactions",
1104
+ "transactions/s",
1105
+ PLUGIN_WINDOWS_NAME,
1106
+ "PerflibMSSQL",
1107
+ PRIO_MSSQL_DATABASE_WRITE_TRANSACTIONS,
1108
+ update_every,
1109
+ RRDSET_TYPE_LINE);
1110
+
1111
+ rrdlabels_add(mli->parent->st_db_write_transactions->rrdlabels,
1112
+ "mssql_instance",
1113
+ mli->parent->instanceID,
1114
+ RRDLABEL_SRC_AUTO);
1115
+
1116
+ rrdlabels_add(mli->parent->st_db_write_transactions->rrdlabels,
1117
+ "database",
1118
+ db,
1119
+ RRDLABEL_SRC_AUTO);
1120
+ }
1121
+
1122
+ if (!mli->rd_db_write_transactions) {
1123
+ snprintfz(id,
1124
+ RRD_ID_LENGTH_MAX,
1125
+ "mssql_db_%s_instance_%s_write_transactions",
1126
+ db,
1127
+ mli->parent->instanceID);
1128
+
1129
+ mli->rd_db_write_transactions = rrddim_add(mli->parent->st_db_write_transactions, id, db,
1130
+ 1, 1, RRD_ALGORITHM_INCREMENTAL);
1131
+ }
1132
+
1133
+ rrddim_set_by_pointer(mli->parent->st_db_write_transactions,
1134
+ mli->rd_db_write_transactions,
1135
+ (collected_number)mli->MSSQLDatabaseWriteTransactions.current.Data);
1136
+}
1137
+
1138
+static void mssql_active_transactions_chart(struct mssql_db_instance *mli, const char *db, int update_every)
1139
+{
1140
+ char id[RRD_ID_LENGTH_MAX + 1];
1141
+ if (!mli->parent->st_db_active_transactions) {
1142
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_active_transactions", db, mli->parent->instanceID);
1143
+ mli->parent->st_db_active_transactions = rrdset_create_localhost("mssql",
1144
+ id,
1145
+ NULL,
1146
+ "transactions",
1147
+ "mssql.database_active_transactions",
1148
+ "Active transactions per database",
1149
+ "transactions",
1150
+ PLUGIN_WINDOWS_NAME,
1151
+ "PerflibMSSQL",
1152
+ PRIO_MSSQL_DATABASE_ACTIVE_TRANSACTIONS,
1153
+ update_every,
1154
+ RRDSET_TYPE_LINE);
1155
+
1156
+ rrdlabels_add(mli->parent->st_db_active_transactions->rrdlabels,
1157
+ "mssql_instance",
1158
+ mli->parent->instanceID,
1159
+ RRDLABEL_SRC_AUTO);
1160
+
1161
+ rrdlabels_add(mli->parent->st_db_active_transactions->rrdlabels,
1162
+ "database",
1163
+ db,
1164
+ RRDLABEL_SRC_AUTO);
1165
+ }
1166
+
1167
+ if (!mli->rd_db_active_transactions) {
1168
+ snprintfz(id,
1169
+ RRD_ID_LENGTH_MAX,
1170
+ "mssql_db_%s_instance_%s_active_transactions",
1171
+ db,
1172
+ mli->parent->instanceID);
1173
+
1174
+ mli->rd_db_active_transactions = rrddim_add(mli->parent->st_db_active_transactions, id, db,
1175
+ 1, 1, RRD_ALGORITHM_ABSOLUTE);
1176
+ }
1177
+
1178
+ rrddim_set_by_pointer(mli->parent->st_db_active_transactions,
1179
+ mli->rd_db_active_transactions,
1180
+ (collected_number)mli->MSSQLDatabaseActiveTransactions.current.Data);
1181
+}
1182
+
1183
+static void mssql_data_file_size_chart(struct mssql_db_instance *mli, const char *db, int update_every)
1184
+{
1185
+ char id[RRD_ID_LENGTH_MAX + 1];
1186
+ if (!mli->parent->st_db_data_file_size) {
1187
+ snprintfz(id, RRD_ID_LENGTH_MAX, "db_%s_instance_%s_data_files_size", db, mli->parent->instanceID);
1188
+ mli->parent->st_db_data_file_size = rrdset_create_localhost("mssql",
1189
+ id,
1190
+ NULL,
1191
+ "size",
1192
+ "mssql.database_data_files_size",
1193
+ "Current database size.",
1194
+ "bytes",
1195
+ PLUGIN_WINDOWS_NAME,
1196
+ "PerflibMSSQL",
1197
+ PRIO_MSSQL_DATABASE_DATA_FILE_SIZE,
1198
+ update_every,
1199
+ RRDSET_TYPE_LINE);
1200
+
1201
+ rrdlabels_add(mli->parent->st_db_data_file_size->rrdlabels,
1202
+ "mssql_instance",
1203
+ mli->parent->instanceID,
1204
+ RRDLABEL_SRC_AUTO);
1205
+
1206
+ rrdlabels_add(mli->parent->st_db_data_file_size->rrdlabels,
1207
+ "database",
1208
+ db,
1209
+ RRDLABEL_SRC_AUTO);
1210
+ }
1211
+
1212
+ if (!mli->rd_db_data_file_size) {
1213
+ snprintfz(id,
1214
+ RRD_ID_LENGTH_MAX,
1215
+ "mssql_db_%s_instance_%s_data_files_size_bytes",
1216
+ db,
1217
+ mli->parent->instanceID);
1218
+
1219
+ mli->rd_db_data_file_size = rrddim_add(mli->parent->st_db_data_file_size, id, db,
1220
+ 1, 1, RRD_ALGORITHM_ABSOLUTE);
1221
+ }
1222
+
1223
+ rrddim_set_by_pointer(mli->parent->st_db_data_file_size,
1224
+ mli->rd_db_data_file_size,
1225
+ (collected_number)mli->MSSQLDatabaseDataFileSize.current.Data*1024);
1226
+
1227
+}
1228
+
1229
+int dict_mssql_databases_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
1230
+{
1231
+ struct mssql_db_instance *mli = value;
1232
+ const char *db = dictionary_acquired_item_name((DICTIONARY_ITEM *)item);
1233
+
1234
+ int *update_every = data;
1235
+
1236
+ void (*transaction_chart[])(struct mssql_db_instance *, const char *, int) = {
1237
+ mssql_data_file_size_chart,
1238
+ mssql_transactions_chart,
1239
+ mssql_database_backup_restore_chart,
1240
+ mssql_database_log_flushed_chart,
1241
+ mssql_database_log_flushes_chart,
1242
+ mssql_active_transactions_chart,
1243
+ mssql_write_transactions_chart,
1244
+
1245
+ // Last function pointer must be NULL
1246
+ NULL
1247
+ };
1248
+
1249
+ int i;
1250
+ for (i = 0; transaction_chart[i]; i++) {
1251
+ transaction_chart[i](mli, db, *update_every);
1252
+ }
1253
+}
1254
+
1255
+static void do_mssql_databases(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p, int update_every)
1256
+{
1257
+ char id[RRD_ID_LENGTH_MAX + 1];
1258
+ PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, p->objectName[NETDATA_MSSQL_DATABASE]);
1259
+ if (!pObjectType) return;
1260
+
1261
+ PERF_INSTANCE_DEFINITION *pi = NULL;
1262
+ for(LONG i = 0; i < pObjectType->NumInstances ; i++) {
1263
+ pi = perflibForEachInstance(pDataBlock, pObjectType, pi);
1264
+ if(!pi) break;
1265
+
1266
+ if(!getInstanceName(pDataBlock, pObjectType, pi, windows_shared_buffer, sizeof(windows_shared_buffer)))
1267
+ strncpyz(windows_shared_buffer, "[unknown]", sizeof(windows_shared_buffer) - 1);
1268
+
1269
+ if(!strcasecmp(windows_shared_buffer, "_Total"))
1270
+ continue;
1271
+
1272
+ netdata_fix_chart_name(windows_shared_buffer);
1273
+ struct mssql_db_instance *mdi = dictionary_set(p->databases,
1274
+ windows_shared_buffer,
1275
+ NULL,
1276
+ sizeof(*mdi));
1277
+ if (!mdi)
1278
+ continue;
1279
+
1280
+ if (!mdi->parent) {
1281
+ mdi->parent = p;
1282
+ }
1283
+
1284
+ perflibGetObjectCounter(pDataBlock, pObjectType, &mdi->MSSQLDatabaseDataFileSize);
1285
+ perflibGetObjectCounter(pDataBlock, pObjectType, &mdi->MSSQLDatabaseActiveTransactions);
1286
+ perflibGetObjectCounter(pDataBlock, pObjectType, &mdi->MSSQLDatabaseBackupRestoreOperations);
1287
+ perflibGetObjectCounter(pDataBlock, pObjectType, &mdi->MSSQLDatabaseLogFlushed);
1288
+ perflibGetObjectCounter(pDataBlock, pObjectType, &mdi->MSSQLDatabaseLogFlushes);
1289
+ perflibGetObjectCounter(pDataBlock, pObjectType, &mdi->MSSQLDatabaseTransactions);
1290
+ perflibGetObjectCounter(pDataBlock, pObjectType, &mdi->MSSQLDatabaseWriteTransactions);
1291
+ }
1292
+
1293
+ dictionary_sorted_walkthrough_read(p->databases, dict_mssql_databases_charts_cb, &update_every);
1294
+ rrdset_done(p->st_db_data_file_size);
1295
+ rrdset_done(p->st_db_active_transactions);
1296
+ rrdset_done(p->st_db_backup_restore_operations);
1297
+ rrdset_done(p->st_db_log_flushed);
1298
+ rrdset_done(p->st_db_log_flushes);
1299
+ rrdset_done(p->st_db_transactions);
1300
+ rrdset_done(p->st_db_write_transactions);
1301
+}
1302
+
1303
+static void do_mssql_memory_mgr(PERF_DATA_BLOCK *pDataBlock, struct mssql_instance *p, int update_every)
1304
+{
1305
+ char id[RRD_ID_LENGTH_MAX + 1];
1306
+ PERF_OBJECT_TYPE *pObjectType = perflibFindObjectTypeByName(pDataBlock, p->objectName[NETDATA_MSSQL_MEMORY]);
1307
+ if (!pObjectType)
1308
+ return;
1309
+
1310
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLConnectionMemoryBytes)) {
1311
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_connection_memory_bytes", p->instanceID);
1312
+ if (!p->st_conn_memory) {
1313
+ p->st_conn_memory = rrdset_create_localhost("mssql"
1314
+ , id, NULL
1315
+ , "memory"
1316
+ , "mssql.instance_memmgr_connection_memory_bytes"
1317
+ , "Amount of dynamic memory to maintain connections"
1318
+ , "bytes"
1319
+ , PLUGIN_WINDOWS_NAME
1320
+ , "PerflibMSSQL"
1321
+ , PRIO_MSSQL_MEMMGR_CONNECTION_MEMORY_BYTES
1322
+ , update_every
1323
+ , RRDSET_TYPE_LINE
1324
+ );
1325
+
1326
+ snprintfz(id, RRD_ID_LENGTH_MAX, "mssql_instance_%s_memmgr_connection_memory_bytes", p->instanceID);
1327
+ p->rd_conn_memory = rrddim_add(p->st_conn_memory,
1328
+ id,
1329
+ "memory",
1330
+ 1,
1331
+ 1,
1332
+ RRD_ALGORITHM_ABSOLUTE);
1333
+
1334
+ rrdlabels_add(p->st_conn_memory->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
1335
+ }
1336
+
1337
+ rrddim_set_by_pointer(p->st_conn_memory,
1338
+ p->rd_conn_memory,
1339
+ (collected_number)(p->MSSQLConnectionMemoryBytes.current.Data*1024));
1340
+ rrdset_done(p->st_conn_memory);
1341
+ }
1342
+
1343
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLExternalBenefitOfMemory)) {
1344
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_external_benefit_of_memory", p->instanceID);
1345
+ if (!p->st_ext_benefit_mem) {
1346
+ p->st_ext_benefit_mem = rrdset_create_localhost("mssql"
1347
+ , id, NULL
1348
+ , "memory"
1349
+ , "mssql.instance_memmgr_external_benefit_of_memory"
1350
+ , "Performance benefit from adding memory to a specific cache"
1351
+ , "bytes"
1352
+ , PLUGIN_WINDOWS_NAME
1353
+ , "PerflibMSSQL"
1354
+ , PRIO_MSSQL_MEMMGR_EXTERNAL_BENEFIT_OF_MEMORY
1355
+ , update_every
1356
+ , RRDSET_TYPE_LINE
1357
+ );
1358
+
1359
+ snprintfz(id, RRD_ID_LENGTH_MAX, "mssql_instance_%s_memmgr_external_benefit_of_memory", p->instanceID);
1360
+ p->rd_ext_benefit_mem = rrddim_add(p->st_ext_benefit_mem,
1361
+ id,
1362
+ "benefit",
1363
+ 1,
1364
+ 1,
1365
+ RRD_ALGORITHM_INCREMENTAL);
1366
+
1367
+ rrdlabels_add(p->st_ext_benefit_mem->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
1368
+ }
1369
+
1370
+ rrddim_set_by_pointer(p->st_ext_benefit_mem,
1371
+ p->rd_ext_benefit_mem,
1372
+ (collected_number)p->MSSQLExternalBenefitOfMemory.current.Data);
1373
+ rrdset_done(p->st_ext_benefit_mem);
1374
+ }
1375
+
1376
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLPendingMemoryGrants)) {
1377
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_pending_memory_grants", p->instanceID);
1378
+ if (!p->st_pending_mem_grant) {
1379
+ p->st_pending_mem_grant = rrdset_create_localhost("mssql"
1380
+ , id, NULL
1381
+ , "memory"
1382
+ , "mssql.instance_memmgr_pending_memory_grants"
1383
+ , "Process waiting for memory grant"
1384
+ , "process"
1385
+ , PLUGIN_WINDOWS_NAME
1386
+ , "PerflibMSSQL"
1387
+ , PRIO_MSSQL_MEMMGR_PENDING_MEMORY_GRANTS
1388
+ , update_every
1389
+ , RRDSET_TYPE_LINE
1390
+ );
1391
+
1392
+ snprintfz(id, RRD_ID_LENGTH_MAX, "mssql_instance_%s_memmgr_pending_memory_grants", p->instanceID);
1393
+ p->rd_pending_mem_grant = rrddim_add(p->st_pending_mem_grant,
1394
+ id,
1395
+ "pending",
1396
+ 1,
1397
+ 1,
1398
+ RRD_ALGORITHM_ABSOLUTE);
1399
+
1400
+ rrdlabels_add(p->st_pending_mem_grant->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
1401
+ }
1402
+
1403
+ rrddim_set_by_pointer(p->st_pending_mem_grant,
1404
+ p->rd_pending_mem_grant,
1405
+ (collected_number)p->MSSQLPendingMemoryGrants.current.Data);
1406
+ rrdset_done(p->st_pending_mem_grant);
1407
+ }
1408
+
1409
+ if (perflibGetObjectCounter(pDataBlock, pObjectType, &p->MSSQLTotalServerMemory)) {
1410
+ snprintfz(id, RRD_ID_LENGTH_MAX, "instance_%s_memmgr_server_memory", p->instanceID);
1411
+ if (!p->st_mem_tot_server) {
1412
+ p->st_mem_tot_server = rrdset_create_localhost("mssql"
1413
+ , id, NULL
1414
+ , "memory"
1415
+ , "mssql.instance_memmgr_server_memory"
1416
+ , "Memory committed"
1417
+ , "bytes"
1418
+ , PLUGIN_WINDOWS_NAME
1419
+ , "PerflibMSSQL"
1420
+ , PRIO_MSSQL_MEMMGR_TOTAL_SERVER
1421
+ , update_every
1422
+ , RRDSET_TYPE_LINE
1423
+ );
1424
+
1425
+ snprintfz(id, RRD_ID_LENGTH_MAX, "mssql_instance_%s_memmgr_total_server_memory_bytes", p->instanceID);
1426
+ p->rd_mem_tot_server = rrddim_add(p->st_mem_tot_server,
1427
+ id,
1428
+ "memory",
1429
+ 1,
1430
+ 1,
1431
+ RRD_ALGORITHM_ABSOLUTE);
1432
+
1433
+ rrdlabels_add(p->st_mem_tot_server->rrdlabels, "mssql_instance", p->instanceID, RRDLABEL_SRC_AUTO);
1434
+ }
1435
+
1436
+ rrddim_set_by_pointer(p->st_mem_tot_server,
1437
+ p->rd_mem_tot_server,
1438
+ (collected_number)(p->MSSQLTotalServerMemory.current.Data*1024));
1439
+ rrdset_done(p->st_mem_tot_server);
1440
+ }
1441
+}
1442
+
1443
int dict_mssql_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
1444
struct mssql_instance *p = value;
1445
int *update_every = data;
@@ -737,10 +1447,11 @@ int dict_mssql_charts_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value
1447
static void (*doMSSQL[])(PERF_DATA_BLOCK *, struct mssql_instance *, int) = {
1448
do_mssql_general_stats,
1449
do_mssql_errors,
740
- NULL, NULL, NULL,
1450
+ do_mssql_databases,
1451
+ do_mssql_locks,
1452
+ do_mssql_memory_mgr,
1453
do_mssql_buffer_management,
1454
do_mssql_sql_statistics,
743
- NULL,
1455
do_mssql_access_methods
1456
};
1457
src/collectors/windows.plugin/windows_plugin.h
+17
@@ -43,6 +43,15 @@ enum PERFLIB_PRIO {
43
44
PRIO_MSSQL_USER_CONNECTIONS,
45
46
+ PRIO_MSSQL_DATABASE_TRANSACTIONS,
47
+ PRIO_MSSQL_DATABASE_ACTIVE_TRANSACTIONS,
48
+ PRIO_MSSQL_DATABASE_WRITE_TRANSACTIONS,
49
+ PRIO_MSSQL_DATABASE_BACKUP_RESTORE_OPERATIONS,
50
+ PRIO_MSSQL_DATABASE_LOG_FLUSHES,
51
+ PRIO_MSSQL_DATABASE_LOG_FLUSHED,
52
+
53
+ PRIO_MSSQL_DATABASE_DATA_FILE_SIZE,
54
+
55
PRIO_MSSQL_STATS_BATCH_REQUEST,
56
PRIO_MSSQL_STATS_COMPILATIONS,
57
PRIO_MSSQL_STATS_RECOMPILATIONS,
@@ -57,6 +66,14 @@ enum PERFLIB_PRIO {
66
PRIO_MSSQL_BUFF_METHODS_PAGE_SPLIT,
67
PRIO_MSSQL_BUFF_PAGE_LIFE_EXPECTANCY,
68
69
+ PRIO_MSSQL_MEMMGR_CONNECTION_MEMORY_BYTES,
70
+ PRIO_MSSQL_MEMMGR_TOTAL_SERVER,
71
+ PRIO_MSSQL_MEMMGR_EXTERNAL_BENEFIT_OF_MEMORY,
72
+ PRIO_MSSQL_MEMMGR_PENDING_MEMORY_GRANTS,
73
+
74
+ PRIO_MSSQL_LOCKS_WAIT,
75
+ PRIO_MSSQL_LOCKS_DEADLOCK,
76
+
77
PRIO_MSSQL_SQL_ERRORS
78
};
79