예제 #1
0
def test_single_file_list(config, app):
    url = "http://localhost:" + text_type(config.flask.port) + "/tuid"
    response = http.post_json(
        url,
        json={
            "meta": {
                "format": "list"
            },
            "from": "files",
            "where": {
                "and": [{
                    "eq": {
                        "revision": "29dcc9cb77c372c97681a47496488ec6c623915d"
                    }
                }, {
                    "in": {
                        "path": ["gfx/thebes/gfxFontVariations.h"]
                    }
                }, {
                    "eq": {
                        "branch": "mozilla-central"
                    }
                }]
            }
        })

    list_response = response.data
    tuids = list_response[0].tuids

    assert len(tuids) == 41  # 41 lines expected
    assert len(set(tuids)) == 41  # tuids much be unique
예제 #2
0
def main():

    try:
        settings = startup.read_settings()
        constants.set(settings.constants)
        Log.start(settings.debug)

        some_failures = http.post_json("http://activedata.allizom.org/query", data={
            "from": "unittest",
            "select": [
                {"name": "branch", "value": "build.branch"},
                {"name": "revision", "value": "build.revision12"},
                {"name": "suite", "value": "run.suite"},
                {"name": "chunk", "value": "run.chunk"},
                {"name": "test", "value": "result.test"}
            ],
            "where": {"and": [
                {"eq": {"result.ok": False}},
                {"gt": {"run.timestamp": Date.today() - WEEK}},
                {"missing": "treeherder.job.note"}
            ]},
            "format": "list",
            "limit": 10
        })


        th = TreeHerder(settings={})

        # th.get_job_classification("mozilla-inbound", "7380457b8ba0")
        for f in some_failures.data:
            th.get_job_classification(f.branch, f.revision)

    except Exception, e:
        Log.error("Problem with etl", e)
예제 #3
0
 def test_big_result_works(self):
     result = http.post_json(global_settings.testing.query,
                             data={
                                 "from": "unittest",
                                 "where": {
                                     "and": [{
                                         "gte": {
                                             "run.timestamp":
                                             Date.today() - DAY
                                         }
                                     }, {
                                         "lt": {
                                             "run.timestamp": Date.today()
                                         }
                                     }, {
                                         "eq": {
                                             "result.ok": False
                                         }
                                     }]
                                 },
                                 "format": "list",
                                 "limit": 10000
                             })
     if result.template:
         result = Except.new_instance(result)
         Log.error("problem with call", cause=result)
     Log.note("Got {{num}} test failures", num=len(result.data))
예제 #4
0
    def test_index_wo_name(self):
        data = {
            "name": "The Parent Trap",
            "released": "29 July` 1998",
            "imdb": "http://www.imdb.com/title/tt0120783/",
            "rating": "PG",
            "director": {
                "name": "Nancy Meyers",
                "dob": "December 8, 1949"
            }
        }
        container = self.utils._es_cluster.get_or_create_index(
            index=TEST_TABLE, kwargs=self.utils._es_test_settings)
        try:
            self.utils._es_cluster.delete_index(container.settings.index)
        except Exception:
            pass
        container = self.utils._es_cluster.get_or_create_index(
            index=TEST_TABLE, kwargs=self.utils._es_test_settings)
        container.add({"value": data})
        container.refresh()

        result = http.post_json(url=self.utils.service_url,
                                json={
                                    "format": "list",
                                    "from": container.settings.index
                                })
        self.assertEqual(result.data, [data])
예제 #5
0
def find_some_work(th):
    # th.get_markup("fx-team", "036f62007472", "B8kS5IJ5Rom8l-kcSIRIlA")
    # th.get_markup("mozilla-inbound", "971c1ee26cad", "fNuzNmZxS6m3i_p9jDh8iA")

    # GET SOME TASKS
    result = http.post_json(url="http://activedata.allizom.org/query",
                            data={
                                "from":
                                "task",
                                "select":
                                ["build.branch", "build.revision", "task.id"],
                                "where": {
                                    "and": [{
                                        "gt": {
                                            "task.run.start_time":
                                            (Date.today() - DAY).unix
                                        }
                                    }, {
                                        "exists": "build.revision"
                                    }, {
                                        "exists": "build.branch"
                                    }]
                                },
                                "format":
                                "list"
                            })

    # TRY TO GET THEM OUT OF OUR CACHE
    for r in result.data:
        Log.note("look for task {{task_id}}", task_id=r.task.id)
        th.get_markup(r.build.branch, r.build.revision, r.task.id)
예제 #6
0
def main():

    try:
        settings = startup.read_settings()
        constants.set(settings.constants)
        Log.start(settings.debug)

        some_failures = http.post_json("http://activedata.allizom.org/query",
                                       data={
                                           "from":
                                           "unittest",
                                           "select": [{
                                               "name": "branch",
                                               "value": "build.branch"
                                           }, {
                                               "name":
                                               "revision",
                                               "value":
                                               "build.revision12"
                                           }, {
                                               "name": "suite",
                                               "value": "run.suite"
                                           }, {
                                               "name": "chunk",
                                               "value": "run.chunk"
                                           }, {
                                               "name": "test",
                                               "value": "result.test"
                                           }],
                                           "where": {
                                               "and": [{
                                                   "eq": {
                                                       "result.ok": False
                                                   }
                                               }, {
                                                   "gt": {
                                                       "run.timestamp":
                                                       Date.today() - WEEK
                                                   }
                                               }, {
                                                   "missing":
                                                   "treeherder.job.note"
                                               }]
                                           },
                                           "format":
                                           "list",
                                           "limit":
                                           10
                                       })

        th = TreeHerder(settings={})

        # th.get_job_classification("mozilla-inbound", "7380457b8ba0")
        for f in some_failures.data:
            th.get_job_classification(f.branch, f.revision)

    except Exception, e:
        Log.error("Problem with etl", e)
예제 #7
0
파일: test_app.py 프로젝트: rv404674/TUID
def test_zero_files(config, app):
    url = "http://localhost:" + text_type(config.flask.port) + "/tuid"
    response = http.post_json(url, json={
        "from": "files",
        "where": {"and": [
            {"eq": {"revision": "29dcc9cb77c372c97681a47496488ec6c623915d"}},
            {"in": {"path": []}},
            {"eq": {"branch": "mozilla-central"}}
        ]}
    })

    assert len(response.data) == 0
예제 #8
0
def move_shards(settings):
    path = settings.elasticsearch.host + ":" + unicode(
        settings.elasticsearch.port)

    command = [{
        "move": {
            "index": "unittest20150803_045709",
            "shard": 20,
            "from_node": "primary",
            "to_node": "tertiary"
        }
    }]

    result = http.post_json(path + "/_cluster/reroute",
                            data={"commands": command})
    Log.note("result {{result}}", result=result)
예제 #9
0
파일: test_app.py 프로젝트: rv404674/TUID
def test_single_file_list(config, app):
    url = "http://localhost:" + text_type(config.flask.port) + "/tuid"
    response = http.post_json(url, json={
        "meta": {"format": "list"},
        "from": "files",
        "where": {"and": [
            {"eq": {"revision": "29dcc9cb77c372c97681a47496488ec6c623915d"}},
            {"in": {"path": ["gfx/thebes/gfxFontVariations.h"]}},
            {"eq": {"branch": "mozilla-central"}}
        ]}
    })

    list_response = response.data
    tuids = list_response[0].tuids

    assert len(tuids) == 41  # 41 lines expected
    assert len(set(tuids)) == 41  # tuids much be unique
예제 #10
0
def one_request(request, please_stop):
    and_op = request.where['and']

    files = []
    for a in and_op:
        if a['in'].path:
            files = a['in'].path
        elif a.eq.path:
            files = [a.eq.path]

    with Timer("Make TUID request from {{timestamp|datetime}}", {"timestamp": request.meta.request_time}):
        try:
            result = http.post_json(
                "http://localhost:5000/tuid",
                json=request,
                timeout=30
            )
            if result is None or len(result.data) != len(files):
                Log.note("incomplete response for {{thread}}", thread=Thread.current().name)
        except Exception as e:
            Log.warning("Request failure", cause=e)
예제 #11
0
def one_request(request, please_stop):
    and_op = request.where['and']

    files = []
    for a in and_op:
        if a['in'].path:
            files = a['in'].path
        elif a.eq.path:
            files = [a.eq.path]

    with Timer("Make TUID request from {{timestamp|datetime}}",
               {"timestamp": request.meta.request_time}):
        try:
            result = http.post_json("http://localhost:5000/tuid",
                                    json=request,
                                    timeout=30)
            if result is None or len(result.data) != len(files):
                Log.note("incomplete response for {{thread}}",
                         thread=Thread.current().name)
        except Exception as e:
            Log.warning("Request failure", cause=e)
예제 #12
0
def find_some_work(th):
    # th.get_markup("fx-team", "036f62007472", "B8kS5IJ5Rom8l-kcSIRIlA")
    # th.get_markup("mozilla-inbound", "971c1ee26cad", "fNuzNmZxS6m3i_p9jDh8iA")

    # GET SOME TASKS
    result = http.post_json(url="http://activedata.allizom.org/query", data={
        "from": "task",
        "select": ["build.branch", "build.revision", "task.id"],
        "where": {"and": [
            {"gt": {"task.run.start_time": (Date.today() - DAY).unix}},
            {"exists": "build.revision"},
            {"exists": "build.branch"}
        ]},
        "format": "list"
    })


    # TRY TO GET THEM OUT OF OUR CACHE
    for r in result.data:
        Log.note("look for task {{task_id}}", task_id=r.task.id)
        th.get_markup(r.build.branch, r.build.revision, r.task.id)
예제 #13
0
def loop_all_days(destination, please_stop):
    try:
        today = Date.today()

        # WHICH DAYS DO WE NEED TO CALCULATE
        # ALL BUILD DATES WITH WITH ETL TIMESTAMP OF A WEEK AGO
        # ALL BUILD DATES THAT HAVE NOT BEEN PROCESSED YET
        build_dates = http.post_json(config.source.url, json={
            "from": "unittest",
            "edges": [
                {
                    "name": "date",
                    "value": "build.date",
                    "allowNulls": False,
                    "domain": {
                        "type": "time",
                        "min": "today-week",
                        "max": "eod",
                        "interval": "day"
                    }
                }
            ],
            "where": {"gte": {"etl.timestamp": (today - WEEK).unix}},
            "sort": {"value": "build.date", "sort": -1},
            "limit": 14,
            "format": "list"
        })

        build_dates.data = jx.sort(build_dates.data, {"value": "date", "sort": -1})

        for d in build_dates.data:
            if please_stop:
                return
            agg(Date(d.date), destination, please_stop=please_stop)
    finally:
        please_stop.go()
예제 #14
0
def test_zero_files(config, app):
    url = "http://localhost:" + text_type(config.flask.port) + "/tuid"
    response = http.post_json(
        url,
        json={
            "from": "files",
            "where": {
                "and": [{
                    "eq": {
                        "revision": "29dcc9cb77c372c97681a47496488ec6c623915d"
                    }
                }, {
                    "in": {
                        "path": []
                    }
                }, {
                    "eq": {
                        "branch": "mozilla-central"
                    }
                }]
            }
        })

    assert len(response.data) == 0
예제 #15
0
    def get_tuids(self, branch, revision, files):
        """
        GET TUIDS FROM ENDPOINT, AND STORE IN DB
        :param branch: BRANCH TO FIND THE REVISION/FILE
        :param revision: THE REVISION NUNMBER
        :param files: THE FULL PATHS TO THE FILES
        :return: MAP FROM FILENAME TO TUID LIST
        """

        # SCRUB INPUTS
        revision = revision[:12]
        files = [file.lstrip('/') for file in files]

        with Timer(
                "ask tuid service for {{num}} files at {{revision|left(12)}}",
            {
                "num": len(files),
                "revision": revision
            },
                silent=not self.enabled):
            response = self.db.query(
                "SELECT file, tuids FROM tuid WHERE revision=" +
                quote_value(revision) + " AND file IN " + quote_list(files))
            found = {file: json2value(tuids) for file, tuids in response.data}

            try:
                remaining = set(files) - set(found.keys())
                new_response = None
                if remaining:
                    request = wrap({
                        "from": "files",
                        "where": {
                            "and": [{
                                "eq": {
                                    "revision": revision
                                }
                            }, {
                                "in": {
                                    "path": remaining
                                }
                            }, {
                                "eq": {
                                    "branch": branch
                                }
                            }]
                        },
                        "branch": branch,
                        "meta": {
                            "format": "list",
                            "request_time": Date.now()
                        }
                    })
                    if self.push_queue is not None:
                        if DEBUG:
                            Log.note(
                                "record tuid request to SQS: {{timestamp}}",
                                timestamp=request.meta.request_time)
                        self.push_queue.add(request)
                    else:
                        if DEBUG:
                            Log.note("no recorded tuid request")

                    if not self.enabled:
                        return found

                    new_response = http.post_json(self.endpoint,
                                                  json=request,
                                                  timeout=self.timeout)

                    with self.db.transaction() as transaction:
                        command = "INSERT INTO tuid (revision, file, tuids) VALUES " + sql_list(
                            quote_list((revision, r.path, value2json(r.tuids)))
                            for r in new_response.data if r.tuids != None)
                        if not command.endswith(" VALUES "):
                            transaction.execute(command)
                    self.num_bad_requests = 0

                found.update(
                    {r.path: r.tuids
                     for r in new_response.data} if new_response else {})
                return found

            except Exception as e:
                self.num_bad_requests += 1
                Till(seconds=SLEEP_ON_ERROR).wait()
                if self.enabled and self.num_bad_requests >= 3:
                    self.enabled = False
                    Log.error("TUID service has problems.", cause=e)
                return found
예제 #16
0
def loop(source, coverage_summary_index, settings, please_stop):
    try:
        cluster = elasticsearch.Cluster(source)
        aliases = cluster.get_aliases()
        candidates = []
        for pairs in aliases:
            if pairs.alias == source.index:
                candidates.append(pairs.index)
        candidates = jx.sort(candidates, {".": "desc"})

        for index_name in candidates:
            coverage_index = elasticsearch.Index(index=index_name, read_only=False, settings=source)
            push_date_filter = unicode2Date(coverage_index.settings.index[-15::], elasticsearch.INDEX_DATE_FORMAT)

            while not please_stop:
                # IDENTIFY NEW WORK
                Log.note("Working on index {{index}}", index=index_name)
                coverage_index.refresh()

                todo = http.post_json(settings.url, json={
                    "from": "coverage",
                    "groupby": ["source.file.name", "build.revision12"],
                    "where": {"and": [
                        {"missing": "source.method.name"},
                        {"missing": "source.file.min_line_siblings"},
                        {"gte": {"repo.push.date": push_date_filter}}
                    ]},
                    "format": "list",
                    "limit": coalesce(settings.batch_size, 100)
                })

                if not todo.data:
                    break

                queue = Queue("pending source files to review")
                queue.extend(todo.data[0:coalesce(settings.batch_size, 100):])

                threads = [
                    Thread.run(
                        "processor" + unicode(i),
                        process_batch,
                        queue,
                        coverage_index,
                        coverage_summary_index,
                        settings,
                        please_stop=please_stop
                    )
                    for i in range(NUM_THREAD)
                ]

                # ADD STOP MESSAGE
                queue.add(Thread.STOP)

                # WAIT FOR THEM TO COMPLETE
                for t in threads:
                    t.join()

        please_stop.go()
        return

    except Exception, e:
        Log.warning("Problem processing", cause=e)
예제 #17
0
def process_batch(todo, coverage_index, coverage_summary_index, settings, please_stop):
    for not_summarized in todo:
        if please_stop:
            return True

        # IS THERE MORE THAN ONE COVERAGE FILE FOR THIS REVISION?
        Log.note("Find dups for file {{file}}", file=not_summarized.source.file.name)
        dups = http.post_json(settings.url, json={
            "from": "coverage",
            "select": [
                {"name": "max_id", "value": "etl.source.id", "aggregate": "max"},
                {"name": "min_id", "value": "etl.source.id", "aggregate": "min"}
            ],
            "where": {"and": [
                {"missing": "source.method.name"},
                {"eq": {
                    "source.file.name": not_summarized.source.file.name,
                    "build.revision12": not_summarized.build.revision12
                }},
            ]},
            "groupby": [
                "test.url"
            ],
            "limit": 100000,
            "format": "list"
        })

        dups_found = False
        for d in dups.data:
            if d.max_id != d.min_id:
                dups_found = True

                Log.note(
                    "removing dups {{details|json}}\n{{dups|json|indent}}",
                    details={
                        "id": int(d.max_id),
                        "test": d.test.url,
                        "source": not_summarized.source.file.name,
                        "revision": not_summarized.build.revision12
                    }
                )

                # FIND ALL INDEXES
                all_indexes = [
                    p.index
                    for p in coverage_index.cluster.get_aliases()
                    if p.alias == coverage_index.settings.alias
                ]
                for index_name in all_indexes:
                    elasticsearch.Index(index=index_name, read_only=False, cluster=coverage_index.cluster).delete_record({"and": [
                        {"not": {"term": {"etl.source.id": int(d.max_id)}}},
                        {"term": {"test.url": d.test.url}},
                        {"term": {"source.file.name": not_summarized.source.file.name}},
                        {"term": {"build.revision12": not_summarized.build.revision12}}
                    ]})
        if dups_found:
            continue

        # LIST ALL TESTS THAT COVER THIS FILE, AND THE LINES COVERED
        test_count = http.post_json(settings.url, json={
            "from": "coverage.source.file.covered",
            "where": {"and": [
                {"missing": "source.method.name"},
                {"eq": {
                    "source.file.name": not_summarized.source.file.name,
                    "build.revision12": not_summarized.build.revision12
                }},
            ]},
            "groupby": [
                "test.url",
                "line"
            ],
            "limit": 100000,
            "format": "list"
        })

        all_tests_covering_file = UNION(test_count.data.get("test.url"))
        num_tests = len(all_tests_covering_file)
        max_siblings = num_tests - 1
        Log.note(
            "{{filename}} rev {{revision}} is covered by {{num}} tests",
            filename=not_summarized.source.file.name,
            num=num_tests,
            revision=not_summarized.build.revision12
        )
        line_summary = list(
            (k, unwrap(wrap(list(v)).get("test.url")))
            for k, v in jx.groupby(test_count.data, keys="line")
        )

        # PULL THE RAW RECORD FOR MODIFICATION
        file_level_coverage_records = http.post_json(settings.url, json={
            "from": "coverage",
            "where": {"and": [
                {"missing": "source.method.name"},
                {"in": {"test.url": all_tests_covering_file}},
                {"eq": {
                    "source.file.name": not_summarized.source.file.name,
                    "build.revision12": not_summarized.build.revision12
                }}
            ]},
            "limit": 100000,
            "format": "list"
        })

        for test_name in all_tests_covering_file:
            siblings = [len(test_names)-1 for g, test_names in line_summary if test_name in test_names]
            min_siblings = MIN(siblings)
            coverage_candidates = jx.filter(file_level_coverage_records.data, lambda row, rownum, rows: row.test.url == test_name)
            if coverage_candidates:

                if len(coverage_candidates) > 1 and any(coverage_candidates[0]._id != c._id for c in coverage_candidates):
                    Log.warning(
                        "Duplicate coverage\n{{cov|json|indent}}",
                        cov=[{"_id": c._id, "run": c.run, "test": c.test} for c in coverage_candidates]
                    )

                # MORE THAN ONE COVERAGE CANDIDATE CAN HAPPEN WHEN THE SAME TEST IS IN TWO DIFFERENT CHUNKS OF THE SAME SUITE
                for coverage_record in coverage_candidates:
                    coverage_record.source.file.max_test_siblings = max_siblings
                    coverage_record.source.file.min_line_siblings = min_siblings
                    coverage_record.source.file.score = (max_siblings - min_siblings) / (max_siblings + min_siblings + 1)
            else:
                example = http.post_json(settings.url, json={
                    "from": "coverage",
                    "where": {"eq": {
                        "test.url": test_name,
                        "source.file.name": not_summarized.source.file.name,
                        "build.revision12": not_summarized.build.revision12
                    }},
                    "limit": 1,
                    "format": "list"
                })

                Log.warning(
                    "{{test|quote}} rev {{revision}} appears to have no coverage for {{file|quote}}!\n{{example|json|indent}}",
                    test=test_name,
                    file=not_summarized.source.file.name,
                    revision=not_summarized.build.revision12,
                    example=example.data[0]
                )

        bad_example = [d for d in file_level_coverage_records.data if d["source.file.min_line_siblings"] == None]
        if bad_example:
            Log.warning("expecting all records to have summary. Example:\n{{example}}", example=bad_example[0])

        rows = [{"id": d._id, "value": d} for d in file_level_coverage_records.data]
        coverage_summary_index.extend(rows)
        coverage_index.extend(rows)

        all_test_summary = []
        for g, records in jx.groupby(file_level_coverage_records.data, "source.file.name"):
            cov = UNION(records.source.file.covered)
            uncov = UNION(records.source.file.uncovered)
            coverage = {
                "_id": "|".join([records[0].build.revision12, g["source.file.name"]]),  # SOMETHING UNIQUE, IN CASE WE RECALCULATE
                "source": {
                    "file": {
                        "name": g["source.file.name"],
                        "is_file": True,
                        "covered": jx.sort(cov, "line"),
                        "uncovered": jx.sort(uncov),
                        "total_covered": len(cov),
                        "total_uncovered": len(uncov),
                        "min_line_siblings": 0  # PLACEHOLDER TO INDICATE DONE
                    }
                },
                "build": records[0].build,
                "repo": records[0].repo,
                "run": records[0].run,
                "etl": {"timestamp": Date.now()}
            }
            all_test_summary.append(coverage)

        sum_rows = [{"id": d["_id"], "value": d} for d in all_test_summary]
        coverage_summary_index.extend(sum_rows)

        if DEBUG:
            coverage_index.refresh()
            todo = http.post_json(settings.url, json={
                "from": "coverage",
                "where": {"and": [
                    {"missing": "source.method.name"},
                    {"missing": "source.file.min_line_siblings"},
                    {"eq": {"source.file.name": not_summarized.source.file.name}},
                    {"eq": {"build.revision12": not_summarized.build.revision12}}
                ]},
                "format": "list",
                "limit": 10
            })
            if todo.data:
                Log.error("Failure to update")
예제 #18
0
def queue_consumer(client, pull_queue, please_stop=None, kwargs=None):
    queue = aws.Queue(pull_queue)
    client = TuidClient(client)
    try_revs = {}
    test_try_revs = True

    #while len(queue) > 0:
    #    request = queue.pop(till=please_stop)
    #    if request:
    #        Log.note("Popping request from {{time}}", time=request.meta.request_time)
    #        queue.commit()

    while not please_stop:
        request = queue.pop(till=please_stop)
        if please_stop:
            break
        if not request:
            Log.note("Nothing in queue, pausing for 5 seconds...")
            (please_stop | Till(seconds=5)).wait()
            continue
        Log.note("Found something in queue")
        repo = 'mozilla-central'

        and_op = request.where['and']

        revision = None
        files = None
        for a in and_op:
            if a.eq.revision:
                revision = a.eq.revision
            elif a['in'].path:
                files = a['in'].path
            elif a.eq.path:
                files = [a.eq.path]

        if len(files) <= 0:
            Log.warning("No files in the given request: {{request}}",
                        request=request)
            continue

        if revision[:12] in try_revs and not test_try_revs:
            Log.warning(
                "Revision {{cset}} does not exist in the {{branch}} branch",
                cset=revision[:12],
                branch='mozilla-central')
            queue.commit()
            continue

        clog_url = HG_URL / 'mozilla-central' / 'json-log' / revision[:12]
        clog_obj = http.get_json(clog_url, retry=RETRY)
        if isinstance(clog_obj, (text_type, str)):
            Log.warning(
                "Revision {{cset}} does not exist in the {{branch}} branch",
                cset=revision[:12],
                branch='mozilla-central')
            try_revs[revision[:12]] = True
            if not test_try_revs:
                queue.commit()
                continue
            else:
                json_rev_url = 'https://hg.mozilla.org/try/json-rev/' + revision[:
                                                                                 12]
                clog_obj = http.get_json(json_rev_url, retry=RETRY)
                if 'phase' not in clog_obj:
                    Log.warning(
                        "Revision {{cset}} does not exist in the try branch",
                        cset=revision[:12],
                        branch='mozilla-central')
                    queue.commit()
                    continue

                if clog_obj['phase'] == 'draft':
                    repo = 'try'

        else:
            Log.note("Revision {{cset}} exists on mozilla-central.",
                     cset=revision[:12])

        request.branch = repo
        with Timer("Make TUID request from {{timestamp|date}}",
                   {"timestamp": request.meta.request_time}):
            client.enabled = True  # ENSURE THE REQUEST IS MADE
            result = http.post_json("http://localhost:5000/tuid",
                                    json=request,
                                    timeout=10000)
            if not client.enabled:
                Log.note("pausing consumer for {{num}}sec",
                         num=PAUSE_ON_FAILURE)
                Till(seconds=PAUSE_ON_FAILURE).wait()
            if result is None or len(result.data) != len(files):
                Log.warning("expecting response for every file requested")

        queue.commit()
예제 #19
0
파일: client.py 프로젝트: rv404674/TUID
    def get_tuids(self, branch, revision, files):
        """
        GET TUIDS FROM ENDPOINT, AND STORE IN DB
        :param branch: BRANCH TO FIND THE REVISION/FILE
        :param revision: THE REVISION NUNMBER
        :param files: THE FULL PATHS TO THE FILES
        :return: MAP FROM FILENAME TO TUID LIST
        """

        # SCRUB INPUTS
        revision = revision[:12]
        files = [file.lstrip('/') for file in files]

        with Timer(
            "ask tuid service for {{num}} files at {{revision|left(12)}}",
            {"num": len(files), "revision": revision},
            silent=not self.enabled
        ):
            response = self.db.query(
                "SELECT file, tuids FROM tuid WHERE revision=" + quote_value(revision) +
                " AND file IN " + quote_list(files)
            )
            found = {file: json2value(tuids) for file, tuids in response.data}

            try:
                remaining = set(files) - set(found.keys())
                new_response = None
                if remaining:
                    request = wrap({
                        "from": "files",
                        "where": {"and": [
                            {"eq": {"revision": revision}},
                            {"in": {"path": remaining}},
                            {"eq": {"branch": branch}}
                        ]},
                        "branch": branch,
                        "meta": {
                            "format": "list",
                            "request_time": Date.now()
                        }
                    })
                    if self.push_queue is not None:
                        if DEBUG:
                            Log.note("record tuid request to SQS: {{timestamp}}", timestamp=request.meta.request_time)
                        self.push_queue.add(request)
                    else:
                        if DEBUG:
                            Log.note("no recorded tuid request")

                    if not self.enabled:
                        return found

                    new_response = http.post_json(
                        self.endpoint,
                        json=request,
                        timeout=self.timeout
                    )

                    with self.db.transaction() as transaction:
                        command = "INSERT INTO tuid (revision, file, tuids) VALUES " + sql_list(
                            quote_list((revision, r.path, value2json(r.tuids)))
                            for r in new_response.data
                            if r.tuids != None
                        )
                        if not command.endswith(" VALUES "):
                            transaction.execute(command)
                    self.num_bad_requests = 0

                found.update({r.path: r.tuids for r in new_response.data} if new_response else {})
                return found

            except Exception as e:
                self.num_bad_requests += 1
                Till(seconds=SLEEP_ON_ERROR).wait()
                if self.enabled and self.num_bad_requests >= 3:
                    self.enabled = False
                    Log.error("TUID service has problems.", cause=e)
                return found
예제 #20
0
def agg(today, destination, debug_filter=None, please_stop=None):
    """
    :param today:  The day we are performing the calculation for
    :param destination: The ES index where we put the results
    :param debug_filter: Some extra limitation to go faster, and focus, for testing
    :param please_stop: Signal for stopping early
    :return: nothing
    """

    # GET LIST OF ALL TESTS, BY PLATFORM, TYPE, SUITE
    for suite in SUITES:
        domain = {"and": [
            {"prefix": {"run.suite": suite}},
            {"gt": {"build.date": (today - 3 * DAY).unix}},
            {"lt": {"build.date": (today + 4 * DAY).unix}},
            {"exists": "build.platform"},
            {"not": {"in": {"build.platform": EXCLUDE_PLATFORMS}}},
            {"not": {"in": {"build.branch": EXCLUDE_BRANCHES}}}
        ]}
        if debug_filter:
            domain['and'].append(debug_filter)

        _ = convert.value2json("\"\"")

        # WE CAN NOT PULL ALL TESTS, THERE ARE TOO MANY, SO DO ONE SUITE AT A TIME
        Log.note("Get summary of failures in {{suite}} for date {{date}}", suite=suite, date=today)
        suite_summary = http.post_json(config.source.url, json={
            "from": "unittest",
            "groupby": [
                {"name": "test", "value": "result.test"}
            ],
            "where": {"and": [
                domain,
                {"eq": {"result.ok": False}}
            ]},
            "format": "list",
            "limit": 100000
        })

        often_fail = jx.filter(suite_summary.data, {"gt": {"count": 1}})

        for g, tests in jx.groupby(often_fail, size=100):
            tests = wrap(tests)
            if please_stop:
                return

            Log.note("Collect stats on {{num}} tests", num=len(tests))
            tests_summary = http.post_json(config.source.url, json={
                "from": "unittest",
                "groupby": [
                    "run.suite",
                    {"name": "test", "value": "result.test"},
                    "build.platform",
                    "build.product",
                    "build.type",
                    "run.type"
                ],
                "select": [
                    {
                        "name": "date_fails",
                        "value": {
                            "mult": [
                                {"div": [{"sub": {"build.date": today + 0.5 * DAY}}, DAY.seconds]},
                                {"when": "result.ok", "then": 0, "else": 1}
                            ]
                        },
                        "aggregate": "stats"
                    },
                    {
                        "name": "date",
                        "value": {"div": [{"sub": {"build.date": today + 0.5 * DAY}}, DAY.seconds]},
                        "aggregate": "stats"
                    },
                    {
                        "name": "fails",
                        "value": {"when": "result.ok", "then": 0, "else": 1},
                        "aggregate": "stats"
                    }
                ],
                "where": {"and": [
                    domain,
                    {"in": {"result.test": tests}}
                ]},
                "format": "list",
                "limit": 100000
            })

            # FOR EACH TEST, CALCULATE THE "RECENTLY BAD" STATISTIC (linear regression slope)
            # THIS IS ONLY A ROUGH CALC FOR TESTING THE UI
            for t in tests_summary.data:
                try:
                    t._id = "-".join([
                        coalesce(t.build.product, ""),
                        t.build.platform,
                        coalesce(t.build.type, ""),
                        coalesce(t.run.type, ""),
                        t.run.suite,
                        t.test,
                        unicode(today.unix)
                    ])
                except Exception, e:
                    Log.error("text join problem", cause=e)
                t.timestamp = today
                t.average = t.fails.avg
                if t.date.var == 0:
                    t.slope = 0
                else:
                    t.slope = (t.date_fails.avg - t.date.avg * t.fails.avg) / t.date.var
                t.etl.timestamp = Date.now()

            # PUSH STATS TO ES
            docs = [{"id": t._id, "value": t} for t in tests_summary.data if t.fails.sum > 0]
            Log.note("Adding {{num}} test summaries", num=len(docs))
            destination.extend(docs)