From d809e5b047213f0cefc9639a469c478a7ea960f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Cavaill=C3=A9?= Date: Tue, 19 May 2015 10:43:57 -0400 Subject: [PATCH] [sqlserver] properly close cursor, avoid leaks We saw memory leak issues with that check. It could have been caused by two different things: * The fact that we are not closing cursors properly, and therefore not freeing properly the recordsets loaded in them * We instantiated wrongly two different cursors in the main check loop letting one leak... --- checks.d/sqlserver.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/checks.d/sqlserver.py b/checks.d/sqlserver.py index cde2f0580a..a0784b74f1 100644 --- a/checks.d/sqlserver.py +++ b/checks.d/sqlserver.py @@ -232,6 +232,8 @@ def get_sql_type(self, instance, counter_name): except Exception, e: self.log.warning("Could not get counter_name of base for metric: %s", e) + self.close_cursor(cursor) + return sql_type, base_name def check(self, instance): @@ -241,13 +243,25 @@ def check(self, instance): custom_tags = instance.get('tags', []) instance_key = self._conn_key(instance) metrics_to_collect = self.instances_metrics[instance_key] - cursor = self.get_cursor(instance) for metric in metrics_to_collect: try: metric.fetch_metric(cursor, custom_tags) except Exception, e: self.log.warning("Could not fetch metric %s: %s" % (metric.datadog_name, e)) + self.close_cursor(cursor) + + def close_cursor(self, cursor): + """ + We close the cursor explicitly b/c we had proven memory leaks + We handle any exception from closing, although according to the doc: + "in adodbapi, it is NOT an error to re-close a closed cursor" + """ + try: + cursor.close() + except Exception as e: + self.log.warning("Could not close adodbapi cursor\n{0}".format(e)) + class SqlServerMetric(object): '''General class for common methods, should never be instantiated directly