Exemple #1
0
def injected_span_pass_to_instance() -> ExternalClass:
    """Inject a span then pass onto an instance."""
    assert wtt.get_current_span().is_recording()

    wtt.get_current_span().set_attribute("Random Int", random.randint(0, 9))
    instance = ExternalClass(wtt.get_current_span())
    instance.disjoint_spanned_method()
    return instance
Exemple #2
0
    def process_with_exception(self) -> None:
        """Do some things and reuse a span."""
        time.sleep(1)
        assert self.span == wtt.get_current_span()
        assert wtt.get_current_span().is_recording()

        # this won't end the span so traces won't be sent,
        # unless the exception is excepted by the caller
        raise Exception("An exception!")
Exemple #3
0
    def process(self) -> None:
        """Do some things and reuse a span."""
        time.sleep(2)
        assert self.span == wtt.get_current_span()
        assert wtt.get_current_span().is_recording()

        # this won't end the span
        try:
            raise KeyError()
        except:  # noqa: E722 # pylint: disable=bare-except
            pass
Exemple #4
0
 def thread_work(worker: int, carrier: Dict[str, Any]) -> int:
     """Do thread's work."""
     assert outter_span.is_recording(
     )  # surprising? this is b/c of shared memory
     assert wtt.get_current_span().is_recording()  # as expected
     assert outter_span != wtt.get_current_span()  # good
     assert wtt.get_current_span(
     )._parent  # type: ignore[attr-defined]  # GREAT!
     # # # #
     print(carrier)
     time.sleep(1)
     return worker
Exemple #5
0
 def thread_work(worker: int, carrier: Dict[str, Any]) -> int:
     """Do thread's work."""
     assert outter_span.is_recording(
     )  # surprising? this is b/c of shared memory
     assert not wtt.get_current_span().is_recording()  # BAD!
     assert outter_span != wtt.get_current_span()  # good
     # assert wtt.get_current_span()._parent # (n/a b/c not recording)
     # # # #
     print(carrier)
     time.sleep(1)
     # shared memory allows this -- but not a great idea logically...
     outter_span.add_event("I'm", {"A": "Thread"})
     return worker
Exemple #6
0
    def thread_work(worker: int) -> int:
        """Do thread's work."""
        assert outter_span.is_recording(
        )  # surprising? this is b/c of shared memory
        assert wtt.get_current_span().is_recording()  # as expected
        assert outter_span != wtt.get_current_span()  # good

        # NOT GOOD!
        assert not wtt.get_current_span()._parent  # type: ignore[attr-defined]

        # # # #
        time.sleep(1)
        return worker
Exemple #7
0
 def thread_work(worker: int, span: wtt.Span) -> int:
     """Do thread's work."""
     assert span == outter_span == wtt.get_current_span()
     assert outter_span.is_recording()  # sure
     assert wtt.get_current_span().is_recording()  # as expected
     assert outter_span == wtt.get_current_span()  # as expected
     assert not wtt.get_current_span()._parent  # type: ignore[attr-defined]
     # # # #
     # print(carrier)
     time.sleep(1)
     # shared memory allows this -- but not a great idea logically...
     outter_span.add_event("I'm", {"A": "Thread"})
     return worker
Exemple #8
0
def example_01_threads_incorrect(n_threads: int) -> None:
    """Run multiple independent threads, INCORRECTLY.

    A non-spanned in-thread function won't be spanned by its *intended*
    parent.

    Don't do this!
    """
    outter_span = wtt.get_current_span()

    def thread_work(worker: int, carrier: Dict[str, Any]) -> int:
        """Do thread's work."""
        assert outter_span.is_recording(
        )  # surprising? this is b/c of shared memory
        assert not wtt.get_current_span().is_recording()  # BAD!
        assert outter_span != wtt.get_current_span()  # good
        # assert wtt.get_current_span()._parent # (n/a b/c not recording)
        # # # #
        print(carrier)
        time.sleep(1)
        # shared memory allows this -- but not a great idea logically...
        outter_span.add_event("I'm", {"A": "Thread"})
        return worker

    futures: List[Future] = []  # type: ignore[type-arg]
    with ThreadPoolExecutor() as pool:
        for i in range(n_threads):
            carrier = wtt.inject_span_carrier()
            print(carrier)
            futures.append(pool.submit(thread_work, i, carrier))

    for worker in as_completed(futures):
        ret = worker.result()
        wtt.add_event("Worker Join", {"worker-id": ret, "type": "thread"})
        print(f"Returned Worker #{ret}")
Exemple #9
0
def example_10_threads(n_threads: int) -> None:
    """Run multiple independent threads, with a common carrier."""
    outter_span = wtt.get_current_span()

    @wtt.spanned(all_args=True, carrier="carrier")
    def thread_work(worker: int, carrier: Dict[str, Any]) -> int:
        """Do thread's work."""
        assert outter_span.is_recording(
        )  # surprising? this is b/c of shared memory
        assert wtt.get_current_span().is_recording()  # as expected
        assert outter_span != wtt.get_current_span()  # good
        assert wtt.get_current_span(
        )._parent  # type: ignore[attr-defined]  # GREAT!
        # # # #
        print(carrier)
        time.sleep(1)
        return worker

    futures: List[Future] = []  # type: ignore[type-arg]
    with ThreadPoolExecutor() as pool:
        for i in range(n_threads):
            carrier = wtt.inject_span_carrier()
            print(carrier)
            futures.append(pool.submit(thread_work, i, carrier))

    for worker in as_completed(futures):
        ret = worker.result()
        wtt.add_event("Worker Join", {"worker-id": ret, "type": "thread"})
        print(f"Returned Worker #{ret}")
Exemple #10
0
    def prepare(self) -> None:
        """Do some things and start an independent span."""
        self.span = wtt.get_current_span()
        assert self.span.is_recording()
        self.span.add_event("(method) started span from instance method")
        time.sleep(3)

        @wtt.respanned(None, wtt.SpanBehavior.END_ON_EXIT, all_args=True)
        def illegal(num: int) -> None:
            # this would end the span before the caller does
            pass

        @wtt.respanned(None, wtt.SpanBehavior.ONLY_END_ON_EXCEPTION, all_args=True)
        def legal_and_rare(num: int) -> None:
            # this could end the span, which may or may not be wanted
            pass

        @wtt.respanned(None, wtt.SpanBehavior.DONT_END, all_args=True)
        def legal_and_fine(num: int) -> None:
            # this is okay, and a quick way to add to the span
            pass

        legal_and_rare(11)
        legal_and_fine(22)
        try:
            illegal(33)
        except wtt.spans.InvalidSpanBehavior:
            assert 1
        else:
            assert 0
Exemple #11
0
    async def get(self) -> None:
        """Write existing fruits."""
        assert tracing_tools.get_current_span().parent.span_id  # type: ignore[attr-defined]

        logging.info("fruits: %r", self.fruit)

        self.write({"fruits": self.fruit})
Exemple #12
0
def example_00_threads_incorrect(n_threads: int) -> None:
    """Run multiple independent threads, INCORRECTLY.

    Spanning an in-thread function will not inherit ANYTHING. The
    resulting span is completely not related in any way to the
    *intended* parent.

    Don't do this!
    """
    outter_span = wtt.get_current_span()

    @wtt.spanned(all_args=True)
    def thread_work(worker: int) -> int:
        """Do thread's work."""
        assert outter_span.is_recording(
        )  # surprising? this is b/c of shared memory
        assert wtt.get_current_span().is_recording()  # as expected
        assert outter_span != wtt.get_current_span()  # good

        # NOT GOOD!
        assert not wtt.get_current_span()._parent  # type: ignore[attr-defined]

        # # # #
        time.sleep(1)
        return worker

    futures: List[Future] = []  # type: ignore[type-arg]
    with ThreadPoolExecutor() as pool:
        for i in range(n_threads):
            futures.append(pool.submit(thread_work, i))

    for worker in as_completed(futures):
        ret = worker.result()
        print(f"Returned Worker #{ret}")
Exemple #13
0
    async def post(self) -> None:
        """Handle a new fruit."""
        assert tracing_tools.get_current_span().parent.span_id  # type: ignore[attr-defined]

        body = json_decode(self.request.body)
        logging.info("body: %r", body)

        self.fruit[body["name"]] = body

        self.write({})
Exemple #14
0
def send(friend: str, myself: str) -> None:
    """Send a message."""
    connection = pika.BlockingConnection(
        pika.ConnectionParameters(host=ADDRESS))
    channel = connection.channel()

    channel.queue_declare(queue=friend)

    go_publish(wtt.get_current_span(), friend, myself, channel)
    connection.close()
Exemple #15
0
    def disjoint_spanned_method(self) -> None:
        """Do some things with a new disjoint span."""
        print("disjoint_spanned_method")
        assert wtt.get_current_span().is_recording()
        assert self.span.is_recording()
        assert self.span != wtt.get_current_span()

        @wtt.evented(all_args=True)
        def inner_event_1(name: str, height: int) -> None:
            print(name)
            print(height)

        @wtt.evented(span="span", all_args=True)
        def inner_event_2(name: str, height: int, span: wtt.Span) -> None:
            assert span.is_recording()
            print(name)
            print(height)

        inner_event_1("Bar", 185)
        inner_event_2("Foo", 177, self.span)
Exemple #16
0
    def get_current_user(self):
        """Get the current user, and set auth-related attributes."""
        try:
            type, token = self.request.headers['Authorization'].split(' ', 1)
            if type.lower() != 'bearer':
                raise Exception('bad header type')
            logger.debug('token: %r', token)
            data = self.auth.validate(token)
            self.auth_data = data
            self.auth_key = token
            if "role" in self.auth_data:
                wtt.get_current_span().set_attribute('self.auth_data.role',
                                                     self.auth_data['role'])
            return data['sub']
        # Auth Failed
        except Exception:
            if self.debug and 'Authorization' in self.request.headers:
                logger.info('Authorization: %r',
                            self.request.headers['Authorization'])
            logger.info('failed auth', exc_info=True)

        return None
Exemple #17
0
    def _prepare(
        self,
        method: str,
        path: str,
        args: Optional[Dict[str, Any]] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> Tuple[str, Dict[str, Any]]:
        """Internal method for preparing requests."""
        if not args:
            args = {}

        # auto-inject the current span's info into the HTTP headers
        if wtt.get_current_span().is_recording():
            wtt.propagations.inject_span_carrier(
                self.session.headers)  # type: ignore[arg-type]

        if path.startswith('/'):
            path = path[1:]
        url = os.path.join(self.address, path)

        kwargs: Dict[str, Any] = {'timeout': self.timeout}

        if method in ('GET', 'HEAD'):
            # args should be urlencoded
            kwargs['params'] = args
        else:
            kwargs['json'] = args

        if self.token_func:
            self._get_token()

        if not headers:
            headers = {}

        if self.access_token:
            headers['Authorization'] = 'Bearer ' + _to_str(self.access_token)

        if headers:
            kwargs['headers'] = headers

        return (url, kwargs)
Exemple #18
0
def example_02_threads_incorrect(n_threads: int) -> None:
    """Run multiple independent threads, INCORRECTLY.

    A re-spanned in-thread function may work, but is NOT SAFE. There's a
    race condition: a parent process/thread may end the span before the
    child thread uses it, or visa-versa. It's not a good idea.

    Don't do this!
    """
    outter_span = wtt.get_current_span()

    # even with `wtt.SpanBehavior.DONT_END`, this isn't a good idea
    @wtt.respanned("span", wtt.SpanBehavior.END_ON_EXIT)
    def thread_work(worker: int, span: wtt.Span) -> int:
        """Do thread's work."""
        assert span == outter_span == wtt.get_current_span()
        assert outter_span.is_recording()  # sure
        assert wtt.get_current_span().is_recording()  # as expected
        assert outter_span == wtt.get_current_span()  # as expected
        assert not wtt.get_current_span()._parent  # type: ignore[attr-defined]
        # # # #
        # print(carrier)
        time.sleep(1)
        # shared memory allows this -- but not a great idea logically...
        outter_span.add_event("I'm", {"A": "Thread"})
        return worker

    futures: List[Future] = []  # type: ignore[type-arg]
    with ThreadPoolExecutor() as pool:
        for i in range(n_threads):
            # carrier = wtt.inject_span_carrier()
            # print(carrier)
            futures.append(pool.submit(thread_work, i, outter_span))

    for worker in as_completed(futures):
        ret = worker.result()
        wtt.add_event("Worker Join", {"worker-id": ret, "type": "thread"})
        print(f"Returned Worker #{ret}")
Exemple #19
0
def the_one_that_returns_a_span() -> wtt.Span:
    """Use wtt.Span-injection to set the span."""
    logging.info("the_one_that_returns_a_span()")
    return wtt.get_current_span()
Exemple #20
0
 def finish(self) -> None:
     """Do some things, reuse a span, then close that span."""
     time.sleep(1)
     assert self.span == wtt.get_current_span()
     assert wtt.get_current_span().is_recording()