def prepare_metrics(obj, org_metric_lookup, valid_levels=[], parent_obj='ContentItem', check_timeseries=True): """ Validate a metric. """ # check if metrics exist and are properly formatted. obj.update(obj.pop('metrics', {})) for k in obj.keys(): m = org_metric_lookup.get(k) if not m: raise RequestError( "Metric '{}' does not exist at this level.".format(k)) if m['faceted'] and not isinstance(obj[k], list): raise RequestError( "Metric '{}' is faceted but was not passed in as a list.". format(k)) if m['faceted'] and not set( obj[k][0].keys()) == set(METRIC_FACET_KEYS): raise RequestError( "Metric '{}' is faceted, but it\'s elements are not properly formatted. " "Each facet must be a dictionary of '{\"facet\":\"facet_name\", \"value\": 1234}" .format(k)) # parse number obj[k] = stats.parse_number(obj[k]) return obj
def prepare_metrics( obj, org_metric_lookup, valid_levels=[], parent_obj='ContentItem', check_timeseries=True ): """ Validate a metric. """ # check if metrics exist and are properly formatted. obj.update(obj.pop('metrics', {})) for k in obj.keys(): m = org_metric_lookup.get(k) if not m: raise RequestError( "Metric '{}' does not exist at this level." .format(k)) if m['faceted'] and not isinstance(obj[k], list): raise RequestError( "Metric '{}' is faceted but was not passed in as a list." .format(k)) if m['faceted'] and not set(obj[k][0].keys()) == set(METRIC_FACET_KEYS): raise RequestError( "Metric '{}' is faceted, but it\'s elements are not properly formatted. " "Each facet must be a dictionary of '{\"facet\":\"facet_name\", \"value\": 1234}" .format(k)) # parse number obj[k] = stats.parse_number(obj[k]) return obj
def _prepare_metrics(obj, metrics_lookup): """ Given a lookup of all metrics this object can contain, validate the object and prepare for ingest. """ # check if metrics exist and are properly formatted. obj.update(obj.pop('metrics', {})) for k in obj.keys(): if k == 'datetime': continue # fetch from lookup m = metrics_lookup.get(k) if not m: raise RequestError( "Metric '{}' does not exist at this level." .format(k)) # validate facet formatting. if m['faceted'] and not isinstance(obj[k], list): raise RequestError( "Metric '{}' is faceted but was not passed in as a list." .format(k)) if m['faceted'] and len(obj[k]) \ and not set(obj[k][0].keys()) == set(METRIC_FACET_KEYS): raise RequestError( "Metric '{}' is faceted, but it\'s elements are not properly formatted. " "Each facet must be a dictionary of '{\"facet\":\"facet_name\", \"value\": 1234}" .format(k)) # remove empty facets if m['faceted'] and not len(obj[k]): obj.pop(k) # parse numbers. if not m['faceted']: obj[k] = stats.parse_number(obj[k]) # parse facet values. else: for i, v in enumerate(obj[k]): obj[k][i]['value'] = \ stats.parse_number(obj[k][i]['value']) return obj
def _prepare_metrics(obj, metrics_lookup): """ Given a lookup of all metrics this object can contain, validate the object and prepare for ingest. """ # check if metrics exist and are properly formatted. obj.update(obj.pop('metrics', {})) for k in obj.keys(): if k == 'datetime': continue # fetch from lookup m = metrics_lookup.get(k) if not m: raise RequestError( "Metric '{}' does not exist at this level.".format(k)) # validate facet formatting. if m['faceted'] and not isinstance(obj[k], list): raise RequestError( "Metric '{}' is faceted but was not passed in as a list.". format(k)) if m['faceted'] and len(obj[k]) \ and not set(obj[k][0].keys()) == set(METRIC_FACET_KEYS): raise RequestError( "Metric '{}' is faceted, but it\'s elements are not properly formatted. " "Each facet must be a dictionary of '{\"facet\":\"facet_name\", \"value\": 1234}" .format(k)) # remove empty facets if m['faceted'] and not len(obj[k]): obj.pop(k) # parse numbers. if not m['faceted']: obj[k] = stats.parse_number(obj[k]) # parse facet values. else: for i, v in enumerate(obj[k]): obj[k][i]['value'] = \ stats.parse_number(obj[k][i]['value']) return obj
def valid_numeric(self, key, opt): """ Validate a numeric option. """ try: return parse_number(opt) except: return RecipeSchemaError( "{} is an 'numeric' field but was passed '{}'." .format(key, opt))
def list_metrics(user, org): # optionally filter by type/level/category include_recipes, exclude_recipes = \ arg_list('recipes', default=[], typ=str, exclusions=True) include_sous_chefs, exclude_sous_chefs = \ arg_list('sous_chefs', default=[], typ=str, exclusions=True) include_types, exclude_types = \ arg_list('types', default=[], typ=str, exclusions=True) include_content_levels, exclude_content_levels = \ arg_list('content_levels', default=[], typ=str, exclusions=True) include_org_levels, exclude_org_levels = \ arg_list('org_levels', default=[], typ=str, exclusions=True) sort_field, direction = arg_sort('sort', default='display_name') faceted = arg_bool('faceted', default=None) # base query metric_query = Metric.query.join(Recipe).join(SousChef) # validate sort fields are part of Recipe object. if sort_field: validate_fields(Metric, fields=[sort_field], suffix='to sort by') # filter by recipes if len(include_recipes): slugs = [] ids = [] for r in include_recipes: try: i = parse_number(r) ids.append(i) except: slugs.append(r) metric_query = metric_query\ .filter(or_(Recipe.id.in_(ids), Recipe.slug.in_(slugs))) if len(exclude_recipes): slugs = [] ids = [] for r in exclude_recipes: try: i = parse_number(r) ids.append(i) except: slugs.append(r) metric_query = metric_query\ .filter(~or_(Recipe.id.in_(ids), Recipe.slug.in_(slugs))) # filter by sous-chefs if len(include_sous_chefs): slugs = [] ids = [] for r in include_sous_chefs: try: i = parse_number(r) ids.append(i) except: slugs.append(r) metric_query = metric_query\ .filter(or_(SousChef.id.in_(ids), SousChef.slug.in_(slugs))) if len(exclude_sous_chefs): slugs = [] ids = [] for r in exclude_sous_chefs: try: i = parse_number(r) ids.append(i) except: slugs.append(r) metric_query = metric_query\ .filter(~or_(SousChef.id.in_(ids), SousChef.slug.in_(slugs))) # filter by levels if len(include_types): metric_query = metric_query\ .filter(Metric.type.in_(include_types)) if len(exclude_types): metric_query = metric_query\ .filter(~Metric.type.in_(exclude_types)) # filter by levels if len(include_content_levels): metric_query = metric_query\ .filter(Metric.content_levels.contains(include_content_levels)) if len(exclude_content_levels): metric_query = metric_query\ .filter(~Metric.content_levels.contains(exclude_content_levels)) if len(include_org_levels): metric_query = metric_query\ .filter(Metric.org_levels.contains(include_org_levels)) if len(exclude_org_levels): metric_query = metric_query\ .filter(~Metric.org_levels.contains(exclude_org_levels)) # filter by faceted if faceted is not None: metric_query = metric_query\ .filter(Metric.faceted == faceted) if sort_field: sort_obj = eval('Metric.{}.{}'.format(sort_field, direction)) metric_query = metric_query.order_by(sort_obj()) facets = defaultdict(Counter) metrics = [] for m in metric_query.all(): facets['recipes'][m.recipe.slug] += 1 facets['types'][m.type] += 1 if 'faceted' in facets: if m.faceted: facets['faceted'] += 1 else: facets['faceted'] = 0 for cl in m.content_levels: facets['content_levels'][cl] += 1 for cl in m.org_levels: facets['org_levels'][cl] += 1 metrics.append(m.to_dict()) resp = { 'metrics': metrics, 'facets': facets } return jsonify(resp)