Exemple #1
0
    async def execute(self,
                      query: str,
                      *args: Any,
                      query_name: Optional[str] = None) -> Optional[int]:
        with wrap2span(
                name=OraSpan.NAME_EXECUTE,
                kind=OraSpan.KIND_CLIENT,
                cls=OraSpan,
                app=self._conn._db.app,
        ) as span:
            span.set_name4adapter(
                self._conn._db.app.logger.ADAPTER_PROMETHEUS,
                OraSpan.P8S_NAME_EXECUTE,
            )
            if query_name is not None:
                span.tag(OraSpan.TAG_QUERY_NAME, query_name)
            async with self._lock:
                if self._conn._db.cfg.log_query:
                    span.annotate(OraSpan.ANN_QUERY, query)
                    span.annotate4adapter(
                        self._conn._db.app.logger.ADAPTER_ZIPKIN,
                        OraSpan.ANN_QUERY,
                        json_encode({'query': str(query)}),
                    )
                    span.annotate(OraSpan.ANN_PARAMS, str(args))
                    span.annotate4adapter(
                        self._conn._db.app.logger.ADAPTER_ZIPKIN,
                        OraSpan.ANN_PARAMS,
                        json_encode({'query_params': str(args)}),
                    )

                await self._loop.run_in_executor(None, self._ora_cur.execute,
                                                 query, args)
                return self._ora_cur.rowcount
Exemple #2
0
def test_encode_bytes() -> None:
    data = os.urandom(100)
    enc_data = json_encode(data)
    assert enc_data == f'"{BASE64_MARKER}{base64.b64encode(data).decode()}"'

    enc_data_ = json.loads(enc_data)[len(BASE64_MARKER):]
    bytes_from_enc_data = base64.b64decode(enc_data_.encode())
    assert data == bytes_from_enc_data
Exemple #3
0
 def _span_ann_format4zipkin(
     self, span: Span, kind: str, content: str, ts: float
 ) -> None:
     span.annotate4adapter(
         self.app.logger.ADAPTER_ZIPKIN,
         kind,
         misc.json_encode({kind: content}),
         ts=ts,
     )
Exemple #4
0
    async def callfunc(self, name: str, return_type: Type, args: list) -> Any:
        with wrap2span(
                name=OraSpan.NAME_CALLFUNC,
                kind=OraSpan.KIND_CLIENT,
                cls=OraSpan,
                app=self._conn._db.app,
        ) as span:
            span.set_name4adapter(
                self._conn._db.app.logger.ADAPTER_PROMETHEUS,
                OraSpan.P8S_NAME_CALLFUNC,
            )
            span.tag(OraSpan.TAG_FUNC_NAME, name)
            async with self._lock:
                if self._conn._db.cfg.log_query:
                    span.annotate(OraSpan.ANN_QUERY,
                                  '%s:%r' % (name, return_type))
                    span.annotate4adapter(
                        self._conn._db.app.logger.ADAPTER_ZIPKIN,
                        OraSpan.ANN_QUERY,
                        json_encode({'proc': '%s:%r' % (name, return_type)}),
                    )
                    span.annotate(OraSpan.ANN_PARAMS, str(args))
                    span.annotate4adapter(
                        self._conn._db.app.logger.ADAPTER_ZIPKIN,
                        OraSpan.ANN_PARAMS,
                        json_encode({'params': str(args)}),
                    )

                # todo timeout
                res = await self._conn._db.loop.run_in_executor(
                    None, self._ora_cur.callfunc, name, return_type, args)

                if self._conn._db.cfg.log_result:
                    span.annotate(OraSpan.ANN_RESULT, str(res))
                    span.annotate4adapter(
                        self._conn._db.app.logger.ADAPTER_ZIPKIN,
                        OraSpan.ANN_RESULT,
                        json_encode({
                            'result': str(res),
                            'args': str(args)
                        }),
                    )

                return res
Exemple #5
0
    async def fetchone(
        self,
        *,
        model_cls: Optional[Type[BaseModel]] = None,
        query_name: Optional[str] = None,
    ) -> Optional[Union[dict, BaseModel]]:
        with wrap2span(
            name=OraSpan.NAME_FETCH,
            kind=OraSpan.KIND_CLIENT,
            cls=OraSpan,
            app=self._conn._db.app,
        ) as span:
            span.set_name4adapter(
                self._conn._db.app.logger.ADAPTER_PROMETHEUS,
                OraSpan.P8S_NAME_FETCH,
            )
            if query_name is not None:
                span.tag(OraSpan.TAG_QUERY_NAME, query_name)
            async with self._lock:
                row = await self._loop.run_in_executor(
                    None, self._ora_cur.fetchone
                )
                res: Optional[Union[dict, BaseModel]] = None
                if row is not None:
                    column_names = [
                        d[0].lower() for d in self._ora_cur.description
                    ]
                    res = dict(zip(column_names, row))

                if self._conn._db.cfg.log_result:
                    span.annotate(OraSpan.ANN_RESULT, json_encode(res))
                    span.annotate4adapter(
                        self._conn._db.app.logger.ADAPTER_ZIPKIN,
                        OraSpan.ANN_RESULT,
                        json_encode({'result': str(res)}),
                    )

                if model_cls is not None and res is not None:
                    return model_cls(**res)  # type: ignore
                else:
                    return res
Exemple #6
0
    def handle(self, span: Span) -> None:  # noqa
        if self.logger is None:  # pragma: no cover
            raise UserWarning
        if self._stopping:  # pragma: no cover
            self.logger.app.log_warn('WTF??? RAHSWS')
        if self._queue is None:  # pragma: no cover
            raise UserWarning

        kwargs: Dict[str, Any] = dict(
            trace_id=span.trace_id,
            stamp_begin=round(span.start_stamp or 0, 6),
            stamp_end=round(span.finish_stamp or 0, 6),
            service=self.cfg.name,
        )

        tags = span.get_tags4adapter(self.name).copy()

        if isinstance(span, ht.HttpSpan):
            kwargs['type'] = 'http'
            kwargs['is_out'] = span.kind != ht.HttpSpan.KIND_SERVER
            if kwargs['is_out']:
                kwargs['type'] += '_out'
            else:
                kwargs['type'] += '_in'

            if ht.HttpSpan.TAG_HTTP_URL in tags:
                kwargs['url'] = tags.pop(ht.HttpSpan.TAG_HTTP_URL)

            if 'rpc.method' in tags:
                kwargs['method'] = tags.pop('rpc.method')
                kwargs['type'] = 'rpc_' + kwargs['type']
            elif ht.HttpSpan.TAG_HTTP_METHOD in tags:
                kwargs['method'] = tags.pop(ht.HttpSpan.TAG_HTTP_METHOD)

            if 'rpc.code' in tags:
                kwargs['status_code'] = tags.pop('rpc.code')
            elif ht.HttpSpan.TAG_HTTP_STATUS_CODE in tags:
                kwargs['status_code'] = tags.pop(
                    ht.HttpSpan.TAG_HTTP_STATUS_CODE)

        elif amqp is not None and isinstance(
                span, (amqp.AmqpInSpan, amqp.AmqpOutSpan)):
            kwargs['type'] = 'amqp'
            kwargs['is_out'] = span.kind != amqp.AmqpSpan.KIND_SERVER
            if kwargs['is_out']:
                kwargs['type'] += '_out'
            else:
                kwargs['type'] += '_in'

            if 'rpc.code' in tags:
                kwargs['status_code'] = tags.pop('rpc.code')

            if 'rpc.method' in tags:
                kwargs['method'] = tags.pop('rpc.method')
                kwargs['type'] = 'rpc_' + kwargs['type']
            else:
                exchange: Optional[str] = None
                routing_key: Optional[str] = None
                if amqp.AmqpSpan.TAG_EXCHANGE in tags:
                    exchange = tags.pop(amqp.AmqpSpan.TAG_EXCHANGE)
                if amqp.AmqpSpan.TAG_ROUTING_KEY in tags:
                    routing_key = tags.pop(amqp.AmqpSpan.TAG_ROUTING_KEY)
                if exchange:
                    kwargs['method'] = 'ex:%s rk:%s' % (
                        exchange or '',
                        routing_key or '',
                    )
                else:
                    kwargs['method'] = 'rk:%s' % (routing_key or '')
                if isinstance(span, amqp.AmqpInSpan):
                    kwargs['method'] = 'receive: %s' % kwargs['method']
                else:
                    kwargs['method'] = 'publish: %s' % kwargs['method']

            if amqp.AmqpSpan.TAG_URL in tags:
                kwargs['url'] = tags.pop(amqp.AmqpSpan.TAG_URL)
        else:
            return

        if Span.TAG_ERROR_MESSAGE in tags:
            kwargs['error'] = tags.pop(Span.TAG_ERROR_MESSAGE)

        anns = span.get_annotations4adapter(self.name).copy()

        for key, ann_name, max_len in self._anns_mapping:
            if ann_name in anns:
                val = "\n\n".join([a for a, _ in anns.pop(ann_name)])
                if len(val) > max_len:
                    val = val[:max_len]
                kwargs[key] = val
            elif key not in kwargs:
                kwargs[key] = None

        # удаляем лишние теги
        ht.HttpSpan.TAG_ERROR in tags and tags.pop(ht.HttpSpan.TAG_ERROR)
        ht.HttpSpan.TAG_ERROR_CLASS in tags and tags.pop(
            ht.HttpSpan.TAG_ERROR_CLASS)
        ht.HttpSpan.TAG_HTTP_HOST in tags and tags.pop(
            ht.HttpSpan.TAG_HTTP_HOST)
        ht.HttpSpan.TAG_HTTP_PATH in tags and tags.pop(
            ht.HttpSpan.TAG_HTTP_PATH)
        ht.HttpSpan.TAG_HTTP_ROUTE in tags and tags.pop(
            ht.HttpSpan.TAG_HTTP_ROUTE)
        ht.HttpSpan.TAG_HTTP_REQUEST_SIZE in tags and tags.pop(
            ht.HttpSpan.TAG_HTTP_REQUEST_SIZE)
        ht.HttpSpan.TAG_HTTP_RESPONSE_SIZE in tags and tags.pop(
            ht.HttpSpan.TAG_HTTP_RESPONSE_SIZE)
        if amqp is not None:
            amqp.AmqpSpan.TAG_CHANNEL_NUMBER in tags and tags.pop(
                amqp.AmqpSpan.TAG_CHANNEL_NUMBER)

        if len(tags) > 0:
            kwargs['tags'] = misc.json_encode(tags)

        self._queue.append(Request(**kwargs))

        if self.cfg.send_max_count <= len(self._queue):
            if self._sleep_fut is not None and not self._sleep_fut.done():
                self._sleep_fut.cancel()
Exemple #7
0
def test_encode_subclass() -> None:
    data = {"uuid": CustomUUID("53fa72dd-16d5-418c-8faa-b6a201202930")}
    json_encode(data)
Exemple #8
0
async def test_success(
    loop,
):
    async with ZipkinServer() as zs:
        cfg = ZipkinConfig(name='123', addr=zs.addr)
        adapter = ZipkinAdapter(cfg)
        app = BaseApplication(BaseConfig())
        app.logger.add(adapter)
        lgr = app.logger
        await lgr.start()

        with lgr.span_new(name='t1', kind=Span.KIND_SERVER) as sp:
            sp.tag('tag', 'abc')
            sp.annotate('k1', 'val1', ts=123456)

            with pytest.raises(Exception):
                with sp.new_child('t2', Span.KIND_CLIENT):
                    raise Exception()

        with lgr.span_new(kind=Span.KIND_SERVER) as sp3:
            sp3.set_name4adapter(lgr.ADAPTER_ZIPKIN, '111')
            sp3.annotate4adapter(
                lgr.ADAPTER_ZIPKIN,
                PgSpan.ANN_RESULT,
                json_encode({'result': '123'}),
                ts=122211000000,
            )
            sp3.set_tag4adapter(
                lgr.ADAPTER_ZIPKIN,
                PgSpan.TAG_QUERY_NAME,
                'get_paym',
            )

        await lgr.stop()

    assert len(zs.spans) == 3

    span: SpanModel = zs.spans[1]
    span2: SpanModel = zs.spans[0]
    span3: SpanModel = zs.spans[2]
    assert span.name == 't1'
    assert span.tags == {'tag': 'abc'}
    assert span.annotations == [
        Annotation(value='val1', timestamp=123456000000)
    ]
    assert span.duration > 0
    assert span.timestamp > 0
    assert not span.debug
    assert span.shared

    assert span2.name == 't2'
    assert span2.tags == {
        'error': 'true',
        'error.class': 'Exception',
        'error.message': '',
    }

    assert 'raise Exception()' in span2.annotations[0].value

    assert span3.name == '111'
    assert span3.tags == {PgSpan.TAG_QUERY_NAME: 'get_paym'}
    assert span3.annotations == [
        Annotation(value='{"result": "123"}', timestamp=122211000000000000)
    ]