def status(self, value): old_status = self._status assert value in status_enum_list if value == self._status: return True roles_accepted = self.roles_accepted.get(value, None) if roles_accepted: perm = Permission(*[RoleNeed(role) for role in roles_accepted]) if not perm.can(): raise RuntimeError("You're not authorized to set this status") status_required = self.status_required.get(value, None) if status_required and self._status != status_required: raise ValueError("You cannot set status from {} to {}".format(self._status, value)) self._status = value self.status_changed() taxi = TaxiM.cache.get(self.taxi_id) taxi.synchronize_status_with_hail(self) client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB']) try: client.write_points([{ "measurement": "hails_status_changed", "tags": { "added_by": User.query.get(self.added_by).email, "operator": self.operateur.email, "zupc": taxi.ads.zupc.insee, "previous_status": old_status, "status": self._status }, "time": datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'), "fields": { "value": 1 } }]) except Exception as e: current_app.logger.error('Influxdb Error: {}'.format(e))
def add_missing_stats(): c = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB']) r = c.query( "select value from hails_status_changed_with_id ORDER BY time LIMIT 1;" ) min_time = r.get_points().next()['time'] fields = [ 'change_to_sent_to_operator', 'change_to_received_by_operator', 'change_to_received_by_taxi', 'change_to_accepted_by_taxi', 'change_to_accepted_by_customer', 'change_to_declined_by_taxi', 'change_to_declined_by_customer', 'change_to_incident_taxi', 'change_to_incident_customer', 'change_to_timeout_taxi', 'change_to_timeout_customer', 'change_to_failure', 'change_to_finished', 'change_to_customer_on_board', 'change_to_timeout_accepted_by_customer', ] q = Hail.query.filter(Hail.added_at <= min_time, or_(*[getattr(Hail, f) != None for f in fields])) for h in q.all(): previous_status = None statuses = [(f[len("change_to_"):], getattr(h, f)) for f in fields] statuses = [v for v in statuses if v[1]] statuses = sorted(statuses, key=lambda v: v[1]) for status in statuses: c.write_points([{ "measurement": "hails_status_changed_with_id", "tags": { "added_by": User.query.get(h.added_by).email, "operator": h.operateur.email, "zupc": h.taxi_relation.ads.zupc.parent.insee, "previous_status": previous_status, "status": status[0], "hail_id": h.id }, "time": status[1].strftime('%Y%m%dT%H:%M:%SZ'), "fields": { "value": 1 } }]) previous_status = status[0]
def post(self): parser = reqparse.DataJSONParser(filter_=hail_expect_post) hj = parser.get_data()[0] hj['status'] = 'received' hail = models.Hail(**hj) models.db.session.add(hail) models.db.session.commit() g.hail_log = models.HailLog('POST', hail, request.data) send_request_operator.apply_async(args=[ hail.id, hail.operateur.hail_endpoint(current_app.config['ENV']), unicode(hail.operateur.operator_header_name), unicode(hail.operateur.operator_api_key), hail.operateur.email ], queue='send_hail_' + current_app.config['NOW']) client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB']) if client: try: client.write_points([{ "measurement": "hails_created", "tags": { "added_by": current_user.email, "operator": operateur.email, "zupc": hail.ads_insee, "geohash": Geohash.encode(hail.customer_lat, hail.customer_lon), }, "time": datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'), "fields": { "value": 1 } }]) except Exception as e: current_app.logger.error('Influxdb Error: {}'.format(e)) result = marshal({"data": [hail]}, hail_model) result['data'][0]['taxi']['lon'] = hail.initial_taxi_lon result['data'][0]['taxi']['lat'] = hail.initial_taxi_lat return result, 201
def get(self): if not request_wants_json(): abort(400, message="request needs JSON") parser = reqparse.RequestParser() parser.add_argument('lon', type=float, required=True, location='args') parser.add_argument('lat', type=float, required=True, location='args') try: args = parser.parse_args() except BadRequest as e: return json.dumps(e.data), 400, {"Content-Type": "application/json"} zupc_list = db.session.execute( """SELECT insee, active, nom FROM "ZUPC" WHERE ST_INTERSECTS(shape, 'POINT(:lon :lat)') AND parent_id = id ORDER BY max_distance ASC;""", args).fetchall() to_return = [] client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB']) for zupc in zupc_list: if any([zupc[0] == z['insee'] for z in to_return]): current_app.logger.debug("ZUPC {} already added, skipping it".format(zupc[0])) continue to_return.append({"insee": zupc[0], "active": zupc[1], "nom": zupc[2]}) if not client: current_app.logger.error("No influxdb client") continue request = """SELECT "value" FROM "nb_taxis_every_1" WHERE "zupc" = '{}' AND "operator" = '' AND time > now() - 1m fill(null) LIMIT 1;""".format(zupc['insee']) try: r = client.query(request) except InfluxDBClientError as e: current_app.logger.error(e) continue points = list(r.get_points()) if len(points) <= 0: current_app.logger.debug("No stat points found, request: \"{}\"".format(request)) continue to_return[-1]['nb_active'] = points[0].get('value') return {"data": to_return}, 200
def status(self, value): old_status = self._status assert value in status_enum_list if value == self._status: return True roles_accepted = self.roles_accepted.get(value, None) if roles_accepted: perm = Permission(*[RoleNeed(role) for role in roles_accepted]) if not perm.can(): raise RuntimeError("You're not authorized to set this status") status_required = self.status_required.get(value, None) if status_required and self._status != status_required: raise ValueError("You cannot set status from {} to {}".format( self._status, value)) self._status = value self.status_changed() taxi = TaxiM.cache.get(self.taxi_id) taxi.synchronize_status_with_hail(self) client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB']) try: client.write_points([{ "measurement": "hails_status_changed", "tags": { "added_by": User.query.get(self.added_by).email, "operator": self.operateur.email, "zupc": taxi.ads.zupc.insee, "previous_status": old_status, "status": self._status }, "time": datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'), "fields": { "value": 1 } }]) except Exception as e: current_app.logger.error('Influxdb Error: {}'.format(e))
def post(self): hj = request.json hj = hj['data'][0] operateur = security_models.User.filter_by_or_404( email=hj['operateur'], message='Unable to find the taxi\'s operateur') descriptions = RawTaxi.get((hj['taxi_id'], ), operateur.id) if len(descriptions) == 0 or len(descriptions[0]) == 0: g.hail_log = HailLog('POST', None, request.data) abort(404, message='Unable to find taxi {} of {}'.format( hj['taxi_id'], hj['operateur'])) if descriptions[0][0]['vehicle_description_status'] != 'free' or\ not TaxiRedis(hj['taxi_id']).is_fresh(hj['operateur']): g.hail_log = HailLog('POST', None, request.data) abort(403, message="The taxi is not available") customer = CustomerModel.query.filter_by( id=hj['customer_id'], moteur_id=current_user.id).first() if not customer: customer = CustomerModel(hj['customer_id']) current_app.extensions['sqlalchemy'].db.session.add(customer) taxi_pos = redis_store.geopos( current_app.config['REDIS_GEOINDEX'], '{}:{}'.format(hj['taxi_id'], operateur.email)) hail = HailModel() hail.customer_id = hj['customer_id'] hail.customer_lon = hj['customer_lon'] hail.customer_lat = hj['customer_lat'] hail.customer_address = hj['customer_address'] hail.customer_phone_number = hj['customer_phone_number'] hail.taxi_id = hj['taxi_id'] hail.initial_taxi_lat = taxi_pos[0][0] if taxi_pos else None hail.initial_taxi_lon = taxi_pos[0][1] if taxi_pos else None hail.operateur_id = operateur.id if customer.ban_end and datetime.now() < customer.ban_end: hail.status = 'customer_banned' current_app.extensions['sqlalchemy'].db.session.add(hail) current_app.extensions['sqlalchemy'].db.session.commit() abort(403, message='Customer is banned') hail.status = 'received' current_app.extensions['sqlalchemy'].db.session.add(hail) current_app.extensions['sqlalchemy'].db.session.commit() g.hail_log = HailLog('POST', hail, request.data) send_request_operator.apply_async(args=[ hail.id, operateur.hail_endpoint(current_app.config['ENV']), unicode(operateur.operator_header_name), unicode(operateur.operator_api_key), operateur.email ], queue='send_hail_' + current_app.config['NOW']) client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB']) try: client.write_points([{ "measurement": "hails_created", "tags": { "added_by": current_user.email, "operator": operateur.email, "zupc": descriptions[0][0]['ads_insee'], }, "time": datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'), "fields": { "value": 1 } }]) except Exception as e: current_app.logger.error('Influxdb Error: {}'.format(e)) result = marshal({"data": [hail]}, hail_model) result['data'][0]['taxi']['lon'] = hail.initial_taxi_lon result['data'][0]['taxi']['lat'] = hail.initial_taxi_lat return result, 201
def store_active_taxis(frequency): now = datetime.utcnow() bound = time() - (Taxi._ACTIVITY_TIMEOUT + frequency * 60) map_operateur_insee_nb_active = dict() map_operateur_nb_active = dict() map_insee_nb_active = dict() active_taxis = set() insee_zupc_dict = dict() prefixed_taxi_ids = [] convert = lambda d: mktime(d.timetuple()) for taxi_id_operator in redis_store.zrangebyscore( current_app.config['REDIS_TIMESTAMPS'], bound, time()): taxi_id, operator = taxi_id_operator.split(':') active_taxis.add(taxi_id) taxi_db = Taxi.query.get(taxi_id) if taxi_db is None: current_app.logger.error('Taxi: {}, not found in database'.format( taxi_id)) continue if taxi_db.ads is None: current_app.logger.error('Taxi: {} is invalid'.format(taxi_id)) continue #This a cache for insee to zupc. if not taxi_db.ads.insee in insee_zupc_dict: zupc = ZUPC.query.get(taxi_db.ads.zupc_id) if not zupc: current_app.logger.error('Unable to find zupc: {}'.format( taxi_db.ads.zupc_id)) zupc = zupc.parent insee_zupc_dict[zupc.insee] = zupc insee_zupc_dict[taxi_db.ads.insee] = zupc else: zupc = insee_zupc_dict[taxi_db.ads.insee] map_insee_nb_active.setdefault(zupc.insee, set()).add(taxi_id) if operator not in map_operateur_insee_nb_active: u = user_datastore.find_user(email=operator) if not u: current_app.logger.error('User: {} not found'.format(operator)) continue map_operateur_insee_nb_active[operator] = dict() map_operateur_insee_nb_active[operator].setdefault(zupc.insee, set()).add(taxi_id) map_operateur_nb_active.setdefault(operator, set()).add(taxi_id) map_operateur_insee_nb_available = dict() map_operateur_nb_available = dict() available_ids = set() for operator, insee_taxi_ids in map_operateur_insee_nb_active.iteritems(): for insee, taxis_ids in insee_taxi_ids.iteritems(): for ids in izip_longest(*[taxis_ids]*100, fillvalue=None): pipe = redis_store.pipeline() for id_ in ids_: pipe.sismember(current_app.config['REDIS_TIMESTAMPS'], i+':'+operator) res = compress(ids, pipe.execute()) map_operateur_insee_nb_available(operator, dict()).setdefault( insee, set()).union(set(res)) available_ids.union(set(res)) for operateur, taxis_ids in map_operateur_nb_active.iteritems(): map_operateur_nb_active.setdefault(operateur, set()).union( set([t+':'+operateur for t in taxis_ids]).intersection(avaliable_ids ) ) client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB']) to_insert = [] bucket_size = 100 def insert(operator, zupc, active, available=False): measurement_name = "nb_taxis_every_{}".format(frequency) if available: measurement_name += '_available' to_insert.append({ "measurement": measurement_name, "tags": { "operator": operator, "zupc": zupc }, "time": now.strftime('%Y%m%dT%H:%M:%SZ'), "fields": { "value": len(active) } } ) if len(to_insert) == 100: current_app.logger.debug('To insert: {}'.format(to_insert)) client.write_points(to_insert) to_insert[:] = [] for operator, zupc_active in map_operateur_insee_nb_active.iteritems(): for zupc, active in zupc_active.iteritems(): insert(operator, zupc, active) for zupc, active in map_insee_nb_active.iteritems(): insert("", zupc, active) for operateur, active in map_operateur_nb_active.iteritems(): insert(operateur, "", active) insert("", "", active_taxis) for operator, zupc_available in map_operateur_insee_nb_active.iteritems(): for zupc, available in zupc_active.iteritems(): insert(operator, zupc, available, True) for zupc, available in map_insee_nb_active.iteritems(): insert("", zupc, available, True) if len(to_insert) > 0: current_app.logger.debug('To insert: {}'.format(to_insert)) client.write_points(to_insert)
def store_active_taxis(frequency): now = datetime.utcnow() map_operateur_insee_nb_active = dict() map_operateur_nb_active = dict() map_insee_nb_active = dict() active_taxis = set() prefixed_taxi_ids = [] convert = lambda d: mktime(d.timetuple()) hidden_operator = current_app.config.get('HIDDEN_OPERATOR', 'testing_operator') for taxi_ids_operator in get_taxis_ids_operators(frequency): taxis = dict() for tm in models.RawTaxi.get([t.split(':')[0] for t in taxi_ids_operator]): for t in tm: taxis[t['taxi_id']+':'+t['u_email']] = t for taxi_id_operator in taxi_ids_operator: taxi_id, operator = taxi_id_operator.split(':') if operator == hidden_operator: continue active_taxis.add(taxi_id) taxi_db = taxis.get(taxi_id_operator, None) if taxi_db is None: current_app.logger.error('Taxi: {}:{}, not found in database'.format( taxi_id, operator)) continue if 'ads_insee' not in taxi_db: current_app.logger.error('Taxi: {} is invalid'.format(taxi_id)) continue #This a cache for insee to zupc. if not taxi_db['ads_insee'] in store_active_taxis.insee_zupc_dict: zupc = models.ZUPC.query.get(taxi_db['ads_zupc_id']) if not zupc: current_app.logger.error('Unable to find zupc: {}'.format( taxi_db['ads_zupc_id'])) continue zupc = zupc.parent store_active_taxis.insee_zupc_dict[zupc.insee] = zupc store_active_taxis.insee_zupc_dict[taxi_db['ads_insee']] = zupc else: zupc = store_active_taxis.insee_zupc_dict[taxi_db['ads_insee']] map_insee_nb_active.setdefault(zupc.insee, set()).add(taxi_id) if operator not in map_operateur_insee_nb_active: u = user_datastore.find_user(email=operator) if not u: current_app.logger.error('User: {} not found'.format(operator)) continue map_operateur_insee_nb_active[operator] = dict() map_operateur_insee_nb_active[operator].setdefault(zupc.insee, set()).add(taxi_id) map_operateur_nb_active.setdefault(operator, set()).add(taxi_id) map_operateur_insee_nb_available = dict() map_operateur_nb_available = dict() available_ids = set() for operator, insee_taxi_ids in map_operateur_insee_nb_active.iteritems(): for insee, taxis_ids in insee_taxi_ids.iteritems(): for ids in pager(taxis_ids, page_size=100): pipe = redis_store.pipeline() for id_ in ids: pipe.zscore(current_app.config['REDIS_TIMESTAMPS'], id_+':'+operator) res = compress(ids, pipe.execute()) map_operateur_insee_nb_available.setdefault(operator, dict()).setdefault( insee, set()).union(set(res)) available_ids.union(set(res)) for operateur, taxis_ids in map_operateur_nb_active.iteritems(): map_operateur_nb_active.setdefault(operateur, set()).union( set([t+':'+operateur for t in taxis_ids]).intersection(available_ids ) ) client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB']) to_insert = [] bucket_size = 100 def insert(operator, zupc, active, available=False): measurement_name = "nb_taxis_every_{}".format(frequency) if available: measurement_name += '_available' to_insert.append({ "measurement": measurement_name, "tags": { "operator": operator, "zupc": zupc }, "time": now.strftime('%Y%m%dT%H:%M:%SZ'), "fields": { "value": len(active) } } ) if len(to_insert) == 100: if client: client.write_points(to_insert) to_insert[:] = [] for operator, zupc_active in map_operateur_insee_nb_active.iteritems(): for zupc, active in zupc_active.iteritems(): insert(operator, zupc, active) for zupc, active in map_insee_nb_active.iteritems(): insert("", zupc, active) for operateur, active in map_operateur_nb_active.iteritems(): insert(operateur, "", active) insert("", "", active_taxis) for operator, zupc_available in map_operateur_insee_nb_active.iteritems(): for zupc, available in zupc_active.iteritems(): insert(operator, zupc, available, True) for zupc, available in map_insee_nb_active.iteritems(): insert("", zupc, available, True) if len(to_insert) > 0: if client: client.write_points(to_insert)
def post(self): hj = request.json hj = hj['data'][0] operateur = security_models.User.filter_by_or_404( email=hj['operateur'], message='Unable to find the taxi\'s operateur') descriptions = RawTaxi.get((hj['taxi_id'],), operateur.id) if len(descriptions) == 0 or len(descriptions[0]) == 0: abort(404, message='Unable to find taxi {} of {}'.format( hj['taxi_id'], hj['operateur'])) if descriptions[0][0]['vehicle_description_status'] != 'free' or\ not TaxiRedis(hj['taxi_id']).is_fresh(hj['operateur']): abort(403, message="The taxi is not available") customer = CustomerModel.query.filter_by(id=hj['customer_id'], operateur_id=current_user.id).first() if not customer: customer = CustomerModel(hj['customer_id']) current_app.extensions['sqlalchemy'].db.session.add(customer) taxi_score = redis_store.zscore(current_app.config['REDIS_GEOINDEX'], '{}:{}'.format(hj['taxi_id'], operateur.email)) r = redis_store.geodecode(int(taxi_score)) if taxi_score else None taxi_pos = r[0] if r else None hail = HailModel() hail.customer_id = hj['customer_id'] hail.customer_lon = hj['customer_lon'] hail.customer_lat = hj['customer_lat'] hail.customer_address = hj['customer_address'] hail.customer_phone_number = hj['customer_phone_number'] hail.taxi_id = hj['taxi_id'] hail.initial_taxi_lat = taxi_pos[0] if r else None hail.initial_taxi_lon = taxi_pos[1] if r else None hail.operateur_id = operateur.id hail.status = 'received' current_app.extensions['sqlalchemy'].db.session.add(hail) current_app.extensions['sqlalchemy'].db.session.commit() g.hail_log = HailLog('POST', hail, request.data) send_request_operator.apply_async(args=[hail.id, operateur.hail_endpoint(current_app.config['ENV']), unicode(operateur.operator_header_name), unicode(operateur.operator_api_key), operateur.email], queue='send_hail_'+current_app.config['NOW']) client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB']) try: client.write_points([{ "measurement": "hails_created", "tags": { "added_by": current_user.email, "operator": operateur.email, "zupc": descriptions[0][0]['ads_insee'], }, "time": datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'), "fields": { "value": 1 } }]) except Exception as e: current_app.logger.error('Influxdb Error: {}'.format(e)) result = marshal({"data": [hail]}, hail_model) result['data'][0]['taxi']['lon'] = hail.initial_taxi_lon result['data'][0]['taxi']['lat'] = hail.initial_taxi_lat return result, 201
def create_influx_db(dbname): c = influx_db.get_client() c.create_database(dbname)
def create_influx_db(dbname): c = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB']) if c: c.create_database(dbname) else: print("There is no client")
def get(self): p = get_parser.parse_args() lon, lat = p['lon'], p['lat'] if current_app.config['LIMITED_ZONE'] and\ not Point(lon, lat).intersects(current_app.config['LIMITED_ZONE']): #It must be 403, but I don't know how our clients will react: return {'data': []} self.zupc_customer = cache_single( """SELECT id, parent_id, max_distance, insee FROM "ZUPC" WHERE ST_INTERSECTS(shape, 'POINT(%s %s)') AND parent_id = id ORDER BY max_distance ASC;""", (lon, lat), "zupc_lon_lat", lambda v: (v['id'], v['parent_id']), get_id=lambda a: (float(a[1].split(",")[0][1:].strip()), float(a[1].split(",")[1][:-1].strip()))) if len(self.zupc_customer) == 0: current_app.logger.debug('No zone found at {}, {}'.format( lat, lon)) return {'data': []} zupc_id = self.zupc_customer[0][0] zupc_insee = self.zupc_customer[0][3] #We can deactivate the max radius for a certain zone inactive_filter_period = current_app.config['INACTIVE_FILTER_PERIOD'] hour = datetime.now().hour if inactive_filter_period[0] > inactive_filter_period[1]: is_inactive = hour >= inactive_filter_period[0] or\ hour <= inactive_filter_period[1] else: is_inactive = inactive_filter_period[ 0] <= hour <= inactive_filter_period[1] if is_inactive: max_distance = current_app.config['DEFAULT_MAX_RADIUS'] else: max_distance = min( filter(lambda v: v > 0, [v[2] for v in self.zupc_customer]) + [current_app.config['DEFAULT_MAX_RADIUS']]) self.check_freshness() g.keys_to_delete = [] name_redis = '{}:{}:{}'.format(lon, lat, time()) g.keys_to_delete.append(name_redis) #It returns a list of all taxis near the given point #For each taxi you have a tuple with: (id, distance, [lat, lon]) nb_positions = redis_store.georadius( current_app.config['REDIS_GEOINDEX_ID'], lat, lon, radius=max_distance / 1000.0, units='km', storedistkey=name_redis) if nb_positions == 0: current_app.logger.debug('No taxi found at {}, {}'.format( lat, lon)) return {'data': []} self.parent_zupc = {r[0]: r[1] for r in self.zupc_customer} self.zupc_customer = { r[0]: r[1] for r in cache_in( 'SELECT id, ST_AsBinary(shape) AS shape FROM "ZUPC" WHERE id in %s', {int(r1[1]) for r1 in self.zupc_customer}, "zupc_parent_shape", lambda v: (v['id'], prep(load_wkb(bytes(v['shape'])))), get_id=lambda v: unicode(v[0])) } taxis = [] offset = 0 count = p['count'] * 4 self.set_not_available(lon, lat, name_redis) while len(taxis) < p['count']: page_ids_distances = [ v for v in redis_store.zrangebyscore(name_redis, 0., '+inf', offset, count, True) if v[0] not in self.not_available ] offset += count if len(page_ids_distances) == 0: break page_ids = [v[0] for v in page_ids_distances] distances = [v[1] for v in page_ids_distances] positions = redis_store.geopos( current_app.config['REDIS_GEOINDEX_ID'], *page_ids) taxis_db = models.RawTaxi.get(page_ids) #We get all timestamps pipe = redis_store.pipeline() map( lambda l_taxis: map( lambda t: pipe.zscore( current_app.config['REDIS_TIMESTAMPS'], t['taxi_id'] + ':' + t['u_email']), l_taxis), taxis_db) timestamps = pipe.execute() #For each member of timestamp_slices we have the first index of the first element #in timestamp, and the index of the last element #If we have taxis_db = [{t_1,}, {,}, {t_21, t_22}, {t_3,}] #Then we want timestamps_slices = [(0, 1), (1, 1), (1, 3), (3, 4)] timestamps_slices = [] map(lambda i: timestamps_slices.append((0, len(i)))\ if not timestamps_slices\ else timestamps_slices.append((timestamps_slices[-1][1], timestamps_slices[-1][1]+len(i))), taxis_db) l = [ models.RawTaxi.generate_dict( t[0], None, None, favorite_operator=p['favorite_operator'], position={ "lon": t[1][1], "lat": t[1][0] }, distance=t[2], timestamps=islice(timestamps, *t[3])) for t in izip( taxis_db, positions, distances, timestamps_slices) if len(t) > 0 if self.filter_zone(t[0], t[1]) ] taxis.extend(filter(None, l)) client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB']) if client: try: client.write_points([{ "measurement": "get_taxis_requests", "tags": { "zupc": zupc_insee, "position": "{:.3f}:{:.3f}".format(float(lon), float(lat)), "moteur": current_user.email, "customer": hashlib.sha224( request.headers.getlist("X-Forwarded-For")[0]. rpartition(' ')[-1] if 'X-Forwarded-For' in request.headers else request.remote_addr or 'untrackable').hexdigest()[:10] }, "time": datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'), "fields": { "value": len(taxis) } }]) except Exception as e: current_app.logger.error('Influxdb Error: {}'.format(e)) return { 'data': sorted(taxis, key=lambda t: t['crowfly_distance'])[:p['count']] }