def __init__(self, port, agentConfig, watchdog=True, skip_ssl_validation=False, use_simple_http_client=False): self._port = int(port) self._agentConfig = agentConfig self._metrics = {} self._dns_cache = None AgentTransaction.set_application(self) AgentTransaction.set_endpoints(agentConfig['endpoints']) if agentConfig['endpoints'] == {}: log.warning( u"No valid endpoint found. Forwarder will drop all incoming payloads." ) AgentTransaction.set_request_timeout(agentConfig['forwarder_timeout']) max_parallelism = self.NO_PARALLELISM # Multiple endpoints => enable parallelism if len(agentConfig['endpoints']) > 1: max_parallelism = self.DEFAULT_PARALLELISM self._tr_manager = TransactionManager(MAX_WAIT_FOR_REPLAY, MAX_QUEUE_SIZE, THROTTLING_DELAY, max_parallelism=max_parallelism) AgentTransaction.set_tr_manager(self._tr_manager) self._watchdog = None self.skip_ssl_validation = skip_ssl_validation or _is_affirmative( agentConfig.get('skip_ssl_validation')) self.agent_dns_caching = _is_affirmative( agentConfig.get('dns_caching')) self.agent_dns_ttl = int(agentConfig.get('dns_ttl', DEFAULT_DNS_TTL)) if self.agent_dns_caching: self._dns_cache = DNSCache(ttl=self.agent_dns_ttl) self.use_simple_http_client = use_simple_http_client if self.skip_ssl_validation: log.info( "Skipping SSL hostname validation, useful when using a transparent proxy" ) # Monitor activity if watchdog: watchdog_timeout = TRANSACTION_FLUSH_INTERVAL * WATCHDOG_INTERVAL_MULTIPLIER / 1000 self._watchdog = Watchdog.create( watchdog_timeout, max_resets=WATCHDOG_HIGH_ACTIVITY_THRESHOLD)
def test_dns_cache(self): side_effects = [(None, None, ['1.1.1.1', '2.2.2.2']), (None, None, ['3.3.3.3'])] mock_resolve = MagicMock(side_effect=side_effects) cache = DNSCache(self.DNS_TTL) with patch('socket.gethostbyaddr', mock_resolve): ip = cache.resolve('foo') self.assertTrue(ip in side_effects[0][2]) sleep(self.DNS_TTL + 1) ip = cache.resolve('foo') self.assertTrue(ip in side_effects[1][2]) # resolve intake endpoint = get_url_endpoint(DEFAULT_ENDPOINT) location = urlparse(endpoint) ip = cache.resolve(location.netloc) self.assertNotEqual(ip, location.netloc)
def __init__(self, port, agentConfig, watchdog=True, skip_ssl_validation=False, use_simple_http_client=False): self._port = int(port) self._agentConfig = agentConfig self._metrics = {} self._dns_cache = None AgentTransaction.set_application(self) AgentTransaction.set_endpoints(agentConfig['endpoints']) if agentConfig['endpoints'] == {}: log.warning(u"No valid endpoint found. Forwarder will drop all incoming payloads.") AgentTransaction.set_request_timeout(agentConfig['forwarder_timeout']) max_parallelism = self.NO_PARALLELISM # Multiple endpoints => enable parallelism if len(agentConfig['endpoints']) > 1: max_parallelism = self.DEFAULT_PARALLELISM self._tr_manager = TransactionManager(MAX_WAIT_FOR_REPLAY, MAX_QUEUE_SIZE, THROTTLING_DELAY, max_parallelism=max_parallelism) AgentTransaction.set_tr_manager(self._tr_manager) self._watchdog = None self.skip_ssl_validation = skip_ssl_validation or _is_affirmative(agentConfig.get('skip_ssl_validation')) self.agent_dns_caching = _is_affirmative(agentConfig.get('dns_caching')) self.agent_dns_ttl = int(agentConfig.get('dns_ttl', DEFAULT_DNS_TTL)) if self.agent_dns_caching: self._dns_cache = DNSCache(ttl=self.agent_dns_ttl) self.use_simple_http_client = use_simple_http_client if self.skip_ssl_validation: log.info("Skipping SSL hostname validation, useful when using a transparent proxy") # Monitor activity if watchdog: watchdog_timeout = TRANSACTION_FLUSH_INTERVAL * WATCHDOG_INTERVAL_MULTIPLIER / 1000 self._watchdog = Watchdog.create(watchdog_timeout, max_resets=WATCHDOG_HIGH_ACTIVITY_THRESHOLD)
class Application(tornado.web.Application): NO_PARALLELISM = 1 DEFAULT_PARALLELISM = 5 def __init__(self, port, agentConfig, watchdog=True, skip_ssl_validation=False, use_simple_http_client=False): self._port = int(port) self._agentConfig = agentConfig self._metrics = {} self._dns_cache = None AgentTransaction.set_application(self) AgentTransaction.set_endpoints(agentConfig['endpoints']) if agentConfig['endpoints'] == {}: log.warning( u"No valid endpoint found. Forwarder will drop all incoming payloads." ) AgentTransaction.set_request_timeout(agentConfig['forwarder_timeout']) max_parallelism = self.NO_PARALLELISM # Multiple endpoints => enable parallelism if len(agentConfig['endpoints']) > 1: max_parallelism = self.DEFAULT_PARALLELISM self._tr_manager = TransactionManager(MAX_WAIT_FOR_REPLAY, MAX_QUEUE_SIZE, THROTTLING_DELAY, max_parallelism=max_parallelism) AgentTransaction.set_tr_manager(self._tr_manager) self._watchdog = None self.skip_ssl_validation = skip_ssl_validation or _is_affirmative( agentConfig.get('skip_ssl_validation')) self.agent_dns_caching = _is_affirmative( agentConfig.get('dns_caching')) self.agent_dns_ttl = int(agentConfig.get('dns_ttl', DEFAULT_DNS_TTL)) if self.agent_dns_caching: self._dns_cache = DNSCache(ttl=self.agent_dns_ttl) self.use_simple_http_client = use_simple_http_client if self.skip_ssl_validation: log.info( "Skipping SSL hostname validation, useful when using a transparent proxy" ) # Monitor activity if watchdog: watchdog_timeout = TRANSACTION_FLUSH_INTERVAL * WATCHDOG_INTERVAL_MULTIPLIER / 1000 self._watchdog = Watchdog.create( watchdog_timeout, max_resets=WATCHDOG_HIGH_ACTIVITY_THRESHOLD) def get_from_dns_cache(self, url): if not self.agent_dns_caching: log.debug('Caching disabled, not resolving.') return url location = urlparse(url) resolve = self._dns_cache.resolve(location.netloc) return "{scheme}://{ip}".format(scheme=location.scheme, ip=resolve) def log_request(self, handler): """ Override the tornado logging method. If everything goes well, log level is DEBUG. Otherwise it's WARNING or ERROR depending on the response code. """ if handler.get_status() < 400: log_method = log.debug elif handler.get_status() < 500: log_method = log.warning else: log_method = log.error request_time = 1000.0 * handler.request.request_time() log_method(u"%d %s %.2fms", handler.get_status(), handler._request_summary(), request_time) def appendMetric(self, prefix, name, host, device, ts, value): if prefix in self._metrics: metrics = self._metrics[prefix] else: metrics = {} self._metrics[prefix] = metrics if name in metrics: metrics[name].append([host, device, ts, value]) else: metrics[name] = [[host, device, ts, value]] def _postMetrics(self): if len(self._metrics) > 0: self._metrics['uuid'] = get_uuid() self._metrics['internalHostname'] = get_hostname(self._agentConfig) self._metrics['apiKey'] = self._agentConfig['api_key'] MetricTransaction(json.dumps(self._metrics), headers={'Content-Type': 'application/json'}) self._metrics = {} def run(self): handlers = [ (r"/intake/?", AgentInputHandler), (r"/intake/metrics?", MetricsAgentInputHandler), (r"/intake/metadata?", MetadataAgentInputHandler), (r"/api/v1/series/?", ApiInputHandler), (r"/api/v1/check_run/?", ApiCheckRunHandler), (r"/status/?", StatusHandler), ] settings = dict( cookie_secret="12oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=", xsrf_cookies=False, debug=False, log_function=self.log_request) non_local_traffic = self._agentConfig.get("non_local_traffic", False) tornado.web.Application.__init__(self, handlers, **settings) http_server = tornado.httpserver.HTTPServer(self) try: # non_local_traffic must be == True to match, not just some non-false value if non_local_traffic is True: http_server.listen(self._port) else: # localhost in lieu of 127.0.0.1 to support IPv6 try: http_server.listen(self._port, address=self._agentConfig['bind_host']) except gaierror: log.warning( "localhost seems undefined in your host file, using 127.0.0.1 instead" ) http_server.listen(self._port, address="127.0.0.1") except socket_error as e: if "Errno 99" in str(e): log.warning( "IPv6 doesn't seem to be fully supported. Falling back to IPv4" ) http_server.listen(self._port, address="127.0.0.1") else: raise except socket_error as e: log.exception( "Socket error %s. Is another application listening on the same port ? Exiting", e) sys.exit(1) except Exception as e: log.exception("Uncaught exception. Forwarder is exiting.") sys.exit(1) log.info("Listening on port %d" % self._port) # Register callbacks self.mloop = tornado.ioloop.IOLoop.current() logging.getLogger().setLevel(get_logging_config()['log_level'] or logging.INFO) def flush_trs(): if self._watchdog: self._watchdog.reset() self._postMetrics() self._tr_manager.flush() tr_sched = tornado.ioloop.PeriodicCallback(flush_trs, TRANSACTION_FLUSH_INTERVAL, io_loop=self.mloop) # Register optional Graphite listener gport = self._agentConfig.get("graphite_listen_port", None) if gport is not None: log.info("Starting graphite listener on port %s" % gport) from graphite import GraphiteServer gs = GraphiteServer(self, get_hostname(self._agentConfig), io_loop=self.mloop) if non_local_traffic is True: gs.listen(gport) else: gs.listen(gport, address="localhost") # Start everything if self._watchdog: self._watchdog.reset() tr_sched.start() self.mloop.start() log.info("Stopped") def stop(self): self.mloop.stop()
class Application(tornado.web.Application): NO_PARALLELISM = 1 DEFAULT_PARALLELISM = 5 def __init__(self, port, agentConfig, watchdog=True, skip_ssl_validation=False, use_simple_http_client=False): self._port = int(port) self._agentConfig = agentConfig self._metrics = {} self._dns_cache = None AgentTransaction.set_application(self) AgentTransaction.set_endpoints(agentConfig['endpoints']) if agentConfig['endpoints'] == {}: log.warning(u"No valid endpoint found. Forwarder will drop all incoming payloads.") AgentTransaction.set_request_timeout(agentConfig['forwarder_timeout']) max_parallelism = self.NO_PARALLELISM # Multiple endpoints => enable parallelism if len(agentConfig['endpoints']) > 1: max_parallelism = self.DEFAULT_PARALLELISM self._tr_manager = TransactionManager(MAX_WAIT_FOR_REPLAY, MAX_QUEUE_SIZE, THROTTLING_DELAY, max_parallelism=max_parallelism) AgentTransaction.set_tr_manager(self._tr_manager) self._watchdog = None self.skip_ssl_validation = skip_ssl_validation or _is_affirmative(agentConfig.get('skip_ssl_validation')) self.agent_dns_caching = _is_affirmative(agentConfig.get('dns_caching')) self.agent_dns_ttl = int(agentConfig.get('dns_ttl', DEFAULT_DNS_TTL)) if self.agent_dns_caching: self._dns_cache = DNSCache(ttl=self.agent_dns_ttl) self.use_simple_http_client = use_simple_http_client if self.skip_ssl_validation: log.info("Skipping SSL hostname validation, useful when using a transparent proxy") # Monitor activity if watchdog: watchdog_timeout = TRANSACTION_FLUSH_INTERVAL * WATCHDOG_INTERVAL_MULTIPLIER / 1000 self._watchdog = Watchdog.create(watchdog_timeout, max_resets=WATCHDOG_HIGH_ACTIVITY_THRESHOLD) def get_from_dns_cache(self, url): if not self.agent_dns_caching: log.debug('Caching disabled, not resolving.') return url location = urlparse(url) resolve = self._dns_cache.resolve(location.netloc) return "{scheme}://{ip}".format(scheme=location.scheme, ip=resolve) def log_request(self, handler): """ Override the tornado logging method. If everything goes well, log level is DEBUG. Otherwise it's WARNING or ERROR depending on the response code. """ if handler.get_status() < 400: log_method = log.debug elif handler.get_status() < 500: log_method = log.warning else: log_method = log.error request_time = 1000.0 * handler.request.request_time() log_method( u"%d %s %.2fms", handler.get_status(), handler._request_summary(), request_time ) def appendMetric(self, prefix, name, host, device, ts, value): if prefix in self._metrics: metrics = self._metrics[prefix] else: metrics = {} self._metrics[prefix] = metrics if name in metrics: metrics[name].append([host, device, ts, value]) else: metrics[name] = [[host, device, ts, value]] def _postMetrics(self): if len(self._metrics) > 0: self._metrics['uuid'] = get_uuid() self._metrics['internalHostname'] = get_hostname(self._agentConfig) self._metrics['apiKey'] = self._agentConfig['api_key'] MetricTransaction(json.dumps(self._metrics), headers={'Content-Type': 'application/json'}) self._metrics = {} def run(self): handlers = [ (r"/intake/?", AgentInputHandler), (r"/intake/metrics?", MetricsAgentInputHandler), (r"/intake/metadata?", MetadataAgentInputHandler), (r"/api/v1/series/?", ApiInputHandler), (r"/api/v1/check_run/?", ApiCheckRunHandler), (r"/status/?", StatusHandler), ] settings = dict( cookie_secret="12oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=", xsrf_cookies=False, debug=False, log_function=self.log_request ) non_local_traffic = self._agentConfig.get("non_local_traffic", False) tornado.web.Application.__init__(self, handlers, **settings) http_server = tornado.httpserver.HTTPServer(self) try: # non_local_traffic must be == True to match, not just some non-false value if non_local_traffic is True: http_server.listen(self._port) else: # localhost in lieu of 127.0.0.1 to support IPv6 try: http_server.listen(self._port, address=self._agentConfig['bind_host']) except gaierror: log.warning("localhost seems undefined in your host file, using 127.0.0.1 instead") http_server.listen(self._port, address="127.0.0.1") except socket_error as e: if "Errno 99" in str(e): log.warning("IPv6 doesn't seem to be fully supported. Falling back to IPv4") http_server.listen(self._port, address="127.0.0.1") else: raise except socket_error as e: log.exception("Socket error %s. Is another application listening on the same port ? Exiting", e) sys.exit(1) except Exception as e: log.exception("Uncaught exception. Forwarder is exiting.") sys.exit(1) log.info("Listening on port %d" % self._port) # Register callbacks self.mloop = tornado.ioloop.IOLoop.current() logging.getLogger().setLevel(get_logging_config()['log_level'] or logging.INFO) def flush_trs(): if self._watchdog: self._watchdog.reset() self._postMetrics() self._tr_manager.flush() tr_sched = tornado.ioloop.PeriodicCallback(flush_trs, TRANSACTION_FLUSH_INTERVAL, io_loop=self.mloop) # Register optional Graphite listener gport = self._agentConfig.get("graphite_listen_port", None) if gport is not None: log.info("Starting graphite listener on port %s" % gport) from graphite import GraphiteServer gs = GraphiteServer(self, get_hostname(self._agentConfig), io_loop=self.mloop) if non_local_traffic is True: gs.listen(gport) else: gs.listen(gport, address="localhost") # Start everything if self._watchdog: self._watchdog.reset() tr_sched.start() self.mloop.start() log.info("Stopped") def stop(self): self.mloop.stop()