gooddata-flight-server 1.34.1.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of gooddata-flight-server might be problematic. Click here for more details.
- gooddata_flight_server/__init__.py +23 -0
- gooddata_flight_server/_version.py +7 -0
- gooddata_flight_server/cli.py +137 -0
- gooddata_flight_server/config/__init__.py +1 -0
- gooddata_flight_server/config/config.py +536 -0
- gooddata_flight_server/errors/__init__.py +1 -0
- gooddata_flight_server/errors/error_code.py +209 -0
- gooddata_flight_server/errors/error_info.py +475 -0
- gooddata_flight_server/exceptions.py +16 -0
- gooddata_flight_server/health/__init__.py +1 -0
- gooddata_flight_server/health/health_check_http_server.py +103 -0
- gooddata_flight_server/health/server_health_monitor.py +83 -0
- gooddata_flight_server/metrics.py +16 -0
- gooddata_flight_server/py.typed +1 -0
- gooddata_flight_server/server/__init__.py +1 -0
- gooddata_flight_server/server/auth/__init__.py +1 -0
- gooddata_flight_server/server/auth/auth_middleware.py +83 -0
- gooddata_flight_server/server/auth/token_verifier.py +62 -0
- gooddata_flight_server/server/auth/token_verifier_factory.py +55 -0
- gooddata_flight_server/server/auth/token_verifier_impl.py +41 -0
- gooddata_flight_server/server/base.py +63 -0
- gooddata_flight_server/server/default.logging.ini +28 -0
- gooddata_flight_server/server/flight_rpc/__init__.py +1 -0
- gooddata_flight_server/server/flight_rpc/flight_middleware.py +162 -0
- gooddata_flight_server/server/flight_rpc/flight_server.py +228 -0
- gooddata_flight_server/server/flight_rpc/flight_service.py +279 -0
- gooddata_flight_server/server/flight_rpc/server_methods.py +200 -0
- gooddata_flight_server/server/server_base.py +321 -0
- gooddata_flight_server/server/server_main.py +116 -0
- gooddata_flight_server/tasks/__init__.py +1 -0
- gooddata_flight_server/tasks/base.py +21 -0
- gooddata_flight_server/tasks/metrics.py +115 -0
- gooddata_flight_server/tasks/task.py +193 -0
- gooddata_flight_server/tasks/task_error.py +60 -0
- gooddata_flight_server/tasks/task_executor.py +96 -0
- gooddata_flight_server/tasks/task_result.py +363 -0
- gooddata_flight_server/tasks/temporal_container.py +247 -0
- gooddata_flight_server/tasks/thread_task_executor.py +639 -0
- gooddata_flight_server/utils/__init__.py +1 -0
- gooddata_flight_server/utils/libc_utils.py +35 -0
- gooddata_flight_server/utils/logging.py +158 -0
- gooddata_flight_server/utils/methods_discovery.py +98 -0
- gooddata_flight_server/utils/otel_tracing.py +142 -0
- gooddata_flight_server-1.34.1.dev1.data/scripts/gooddata-flight-server +10 -0
- gooddata_flight_server-1.34.1.dev1.dist-info/LICENSE.txt +7 -0
- gooddata_flight_server-1.34.1.dev1.dist-info/METADATA +749 -0
- gooddata_flight_server-1.34.1.dev1.dist-info/RECORD +49 -0
- gooddata_flight_server-1.34.1.dev1.dist-info/WHEEL +5 -0
- gooddata_flight_server-1.34.1.dev1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# (C) 2024 GoodData Corporation
|
|
2
|
+
"""
|
|
3
|
+
Logging configuration helper functions
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
from logging.config import fileConfig
|
|
8
|
+
from typing import Any, Optional, Union
|
|
9
|
+
|
|
10
|
+
import orjson
|
|
11
|
+
import structlog
|
|
12
|
+
from opentelemetry import trace
|
|
13
|
+
from structlog.typing import EventDict, WrappedLogger
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _resolve_config(logging_ini: str, for_module: Optional[str]) -> str:
|
|
17
|
+
if os.path.isabs(logging_ini):
|
|
18
|
+
return logging_ini
|
|
19
|
+
else:
|
|
20
|
+
conf_dir = os.path.dirname(for_module) if for_module is not None else os.path.curdir
|
|
21
|
+
|
|
22
|
+
return os.path.join(conf_dir, logging_ini)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class _ORJsonRenderer:
|
|
26
|
+
def __init__(self, output_bytes: bool = False):
|
|
27
|
+
self._output_bytes = output_bytes
|
|
28
|
+
|
|
29
|
+
@staticmethod
|
|
30
|
+
def default(obj: Any) -> Any:
|
|
31
|
+
# sets are not serializable by default, so convert them to lists
|
|
32
|
+
if isinstance(obj, set):
|
|
33
|
+
return list(obj)
|
|
34
|
+
# otherwise, do nothing, this will make the default logic to kick in
|
|
35
|
+
|
|
36
|
+
def __call__(self, logger: Any, name: str, event_dict: Any) -> Union[str, bytes]:
|
|
37
|
+
if self._output_bytes:
|
|
38
|
+
return orjson.dumps(event_dict, default=_ORJsonRenderer.default)
|
|
39
|
+
|
|
40
|
+
return orjson.dumps(event_dict, default=_ORJsonRenderer.default).decode("UTF-8")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class _OtelTraceContextInjector:
|
|
44
|
+
"""
|
|
45
|
+
Injects trace id, span id and parent span id obtained from current OpenTelemetry span.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
__slots__ = ("_trace_id_key", "_span_id_key", "_parent_span_id_key")
|
|
49
|
+
|
|
50
|
+
def __init__(self, trace_ctx_keys: Optional[dict[str, str]] = None) -> None:
|
|
51
|
+
_keys = trace_ctx_keys or {}
|
|
52
|
+
|
|
53
|
+
# do one-time lookup of the actual key names under which the different
|
|
54
|
+
# otel info should be hammered. this exists here because server allows
|
|
55
|
+
# admins to provide mapping between default trace/span/parent span
|
|
56
|
+
# and desired key names.
|
|
57
|
+
#
|
|
58
|
+
# the mapping exists to improve fit into different contexts where
|
|
59
|
+
# server is integrated. the default 'trace_id' and 'span_id' keys may
|
|
60
|
+
# thwart observability experience if the rest of the system uses say 'traceId'
|
|
61
|
+
# and 'spanId'.
|
|
62
|
+
self._trace_id_key = _keys.get("trace_id", "trace_id")
|
|
63
|
+
self._span_id_key = _keys.get("span_id", "span_id")
|
|
64
|
+
self._parent_span_id_key = _keys.get("parent_span_id", "parent_span_id")
|
|
65
|
+
|
|
66
|
+
def __call__(self, _: WrappedLogger, __: str, event_dict: EventDict) -> EventDict:
|
|
67
|
+
span = trace.get_current_span()
|
|
68
|
+
if span == trace.INVALID_SPAN:
|
|
69
|
+
# bail out right away if the current span is not valid
|
|
70
|
+
#
|
|
71
|
+
# most typically, this happens if the log is being emitted while there is no
|
|
72
|
+
# current span set (e.g. code runs outside a trace span -> very valid scenario)
|
|
73
|
+
return event_dict
|
|
74
|
+
|
|
75
|
+
span_ctx = span.get_span_context()
|
|
76
|
+
event_dict[self._trace_id_key] = f"{span_ctx.trace_id:x}"
|
|
77
|
+
event_dict[self._span_id_key] = f"{span_ctx.span_id:x}"
|
|
78
|
+
|
|
79
|
+
parent_ctx: Optional[trace.SpanContext] = getattr(span, "parent", None)
|
|
80
|
+
if parent_ctx:
|
|
81
|
+
event_dict[self._parent_span_id_key] = f"{parent_ctx.span_id:x}"
|
|
82
|
+
|
|
83
|
+
return event_dict
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _configure_structlog(
|
|
87
|
+
dev_log: bool,
|
|
88
|
+
event_key: str,
|
|
89
|
+
add_trace_ctx: bool = False,
|
|
90
|
+
trace_ctx_keys: Optional[dict[str, str]] = None,
|
|
91
|
+
) -> None:
|
|
92
|
+
common_processors: list[Any] = [
|
|
93
|
+
structlog.stdlib.filter_by_level,
|
|
94
|
+
structlog.contextvars.merge_contextvars,
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
if add_trace_ctx:
|
|
98
|
+
common_processors.append(_OtelTraceContextInjector(trace_ctx_keys))
|
|
99
|
+
|
|
100
|
+
common_processors.extend(
|
|
101
|
+
[
|
|
102
|
+
structlog.stdlib.add_logger_name,
|
|
103
|
+
structlog.stdlib.add_log_level,
|
|
104
|
+
structlog.stdlib.PositionalArgumentsFormatter(),
|
|
105
|
+
structlog.processors.TimeStamper(fmt="iso"),
|
|
106
|
+
structlog.processors.StackInfoRenderer(),
|
|
107
|
+
structlog.processors.format_exc_info,
|
|
108
|
+
structlog.processors.UnicodeDecoder(),
|
|
109
|
+
]
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
if dev_log:
|
|
113
|
+
processors: Any = common_processors + [structlog.dev.ConsoleRenderer()]
|
|
114
|
+
else:
|
|
115
|
+
processors = common_processors + [
|
|
116
|
+
structlog.processors.EventRenamer(event_key),
|
|
117
|
+
_ORJsonRenderer(),
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
structlog.configure(
|
|
121
|
+
processors=processors,
|
|
122
|
+
wrapper_class=structlog.stdlib.BoundLogger,
|
|
123
|
+
logger_factory=structlog.stdlib.LoggerFactory(),
|
|
124
|
+
cache_logger_on_first_use=True,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def init_logging(
|
|
129
|
+
logging_ini: str,
|
|
130
|
+
dev_log: bool = False,
|
|
131
|
+
event_key: str = "event",
|
|
132
|
+
for_module: Optional[str] = None,
|
|
133
|
+
add_trace_ctx: bool = False,
|
|
134
|
+
trace_ctx_keys: Optional[dict[str, str]] = None,
|
|
135
|
+
) -> str:
|
|
136
|
+
"""
|
|
137
|
+
Initializes python logging from the file on the provided path. If the path is absolute, then it is
|
|
138
|
+
used as is. Otherwise lookup is done for a file relative to the provided module if it is specified; if not
|
|
139
|
+
specified, lookup is done for file relative to the current directory.
|
|
140
|
+
|
|
141
|
+
:param logging_ini: path to logging ini file
|
|
142
|
+
:param dev_log: specify true to configure logging in development mode; this mode is more convenient
|
|
143
|
+
during dev testing but not so suitable for production
|
|
144
|
+
:param event_key: name of the event key (default event)
|
|
145
|
+
:param for_module: optionally specify, module pathname; relative file config will be resolved
|
|
146
|
+
in regard to this module directory; otherwise goes against current dir
|
|
147
|
+
:param add_trace_ctx: optionally specify whether logging pipeline should include processor that hammers in
|
|
148
|
+
otel tracing information (trace id, span id)
|
|
149
|
+
:param trace_ctx_keys: optionally specify mapping for key names under which trace context will be dumped into
|
|
150
|
+
log events. default values are 'trace_id', 'span_id' and 'parent_span_id'. The mapping allows to override
|
|
151
|
+
those key names
|
|
152
|
+
:return: pathname of log file that was used to configure
|
|
153
|
+
"""
|
|
154
|
+
log_config = _resolve_config(logging_ini, for_module)
|
|
155
|
+
fileConfig(log_config)
|
|
156
|
+
_configure_structlog(dev_log, event_key, add_trace_ctx, trace_ctx_keys)
|
|
157
|
+
|
|
158
|
+
return log_config
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# (C) 2024 GoodData Corporation
|
|
2
|
+
import importlib
|
|
3
|
+
from functools import wraps
|
|
4
|
+
from inspect import signature
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from gooddata_flight_server.exceptions import FlightMethodsModuleError
|
|
8
|
+
from gooddata_flight_server.server.base import (
|
|
9
|
+
FlightServerMethods,
|
|
10
|
+
FlightServerMethodsFactory,
|
|
11
|
+
ServerContext,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def flight_server_methods(fun: FlightServerMethodsFactory) -> FlightServerMethodsFactory:
|
|
16
|
+
"""
|
|
17
|
+
Decorator that marks a function as the FlightServerMethodsFactory to be used.
|
|
18
|
+
Any module that should provide the methods factory should contain exactly one function decorated with this decorator.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
@wraps(fun)
|
|
22
|
+
def wrapped(ctx: ServerContext) -> FlightServerMethods:
|
|
23
|
+
return fun(ctx)
|
|
24
|
+
|
|
25
|
+
wrapped.__is_flight_server_methods__ = True # type: ignore
|
|
26
|
+
return wrapped
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _is_flight_server_methods(obj: object) -> bool:
|
|
30
|
+
"""
|
|
31
|
+
Checks whether the object is a FlightServerMethods.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
return getattr(obj, "__is_flight_server_methods__", False)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _is_valid_flight_methods_factory(obj: object) -> bool:
|
|
38
|
+
"""
|
|
39
|
+
Check whether the object is a valid FlightServerMethodsFactory.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
return callable(obj) and len(signature(obj).parameters) == 1
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _only_valid_flight_methods_factory(
|
|
46
|
+
module_name: str, factories: list[FlightServerMethodsFactory]
|
|
47
|
+
) -> FlightServerMethodsFactory:
|
|
48
|
+
"""
|
|
49
|
+
Validate the list of factories and return the only valid one.
|
|
50
|
+
"""
|
|
51
|
+
if len(factories) == 0:
|
|
52
|
+
raise FlightMethodsModuleError(
|
|
53
|
+
f"No flight methods factory found in the module {module_name}. "
|
|
54
|
+
"Make sure the module exports exactly one function decorated with the `@flight_server_methods` decorator "
|
|
55
|
+
"that conforms to the FlightMethodsFactory protocol."
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
if len(factories) > 1:
|
|
59
|
+
raise FlightMethodsModuleError(
|
|
60
|
+
f"Multiple flight methods factories ({len(factories)}) found in the module {module_name}"
|
|
61
|
+
"Make sure the module exports exactly one function decorated with the `@flight_server_methods` decorator "
|
|
62
|
+
"that conforms to the FlightMethodsFactory protocol."
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
factory = factories[0]
|
|
66
|
+
|
|
67
|
+
if not _is_valid_flight_methods_factory(factory):
|
|
68
|
+
raise FlightMethodsModuleError(
|
|
69
|
+
f"Invalid flight methods factory in the module {module_name}. "
|
|
70
|
+
"Make sure the function conforms to the FlightMethodsFactory protocol: "
|
|
71
|
+
"that it takes the correct number of arguments and returns an instance of FlightServerMethods."
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
return factory
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_methods_factory(module_name: str, root: Optional[str] = None) -> FlightServerMethodsFactory:
|
|
78
|
+
"""
|
|
79
|
+
Get the method factory from the given module.
|
|
80
|
+
The module should contain exactly one method decorated with @flight_server_methods.
|
|
81
|
+
|
|
82
|
+
:param module_name: name of the module containing the methods abstract factory.
|
|
83
|
+
:param root: root package of the module: this is used to resolve relative module names (mainly useful in tests).
|
|
84
|
+
:return: a FlightServerMethodsFactory
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
module = importlib.import_module(module_name, package=root)
|
|
89
|
+
except ModuleNotFoundError as e:
|
|
90
|
+
raise FlightMethodsModuleError(f"Flight methods module {module_name} not found.") from e
|
|
91
|
+
|
|
92
|
+
factories: list[FlightServerMethodsFactory] = [
|
|
93
|
+
member.__wrapped__ # unwrap the actual instance from the marker decorator to keep the type
|
|
94
|
+
for member in module.__dict__.values()
|
|
95
|
+
if _is_flight_server_methods(member)
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
return _only_valid_flight_methods_factory(module_name, factories)
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# (C) 2024 GoodData Corporation
|
|
2
|
+
import os
|
|
3
|
+
import platform
|
|
4
|
+
import socket
|
|
5
|
+
import sys
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from opentelemetry import trace
|
|
9
|
+
from opentelemetry.sdk.resources import (
|
|
10
|
+
OS_DESCRIPTION,
|
|
11
|
+
OS_TYPE,
|
|
12
|
+
PROCESS_PARENT_PID,
|
|
13
|
+
PROCESS_PID,
|
|
14
|
+
PROCESS_RUNTIME_DESCRIPTION,
|
|
15
|
+
PROCESS_RUNTIME_NAME,
|
|
16
|
+
PROCESS_RUNTIME_VERSION,
|
|
17
|
+
SERVICE_INSTANCE_ID,
|
|
18
|
+
SERVICE_NAME,
|
|
19
|
+
SERVICE_NAMESPACE,
|
|
20
|
+
SERVICE_VERSION,
|
|
21
|
+
Resource,
|
|
22
|
+
)
|
|
23
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
24
|
+
from opentelemetry.sdk.trace.export import (
|
|
25
|
+
BatchSpanProcessor,
|
|
26
|
+
ConsoleSpanExporter,
|
|
27
|
+
SpanExporter,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
from gooddata_flight_server._version import __version__
|
|
31
|
+
from gooddata_flight_server.config.config import OtelConfig, OtelExporterType
|
|
32
|
+
|
|
33
|
+
SERVER_TRACER: trace.Tracer = trace.ProxyTracer("gooddata_flight_server")
|
|
34
|
+
"""
|
|
35
|
+
Tracer to use for all spans created within the server - all code in this package should
|
|
36
|
+
use this one single tracer.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _create_console_span_exporter() -> SpanExporter:
|
|
41
|
+
return ConsoleSpanExporter()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _create_zipkin_span_exporter() -> SpanExporter:
|
|
45
|
+
from opentelemetry.exporter.zipkin.json import (
|
|
46
|
+
ZipkinExporter, # type: ignore
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return ZipkinExporter()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _create_otlp_grpc_exporter() -> SpanExporter:
|
|
53
|
+
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
|
|
54
|
+
OTLPSpanExporter, # type: ignore
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
return OTLPSpanExporter()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _create_otlp_http_exporter() -> SpanExporter:
|
|
61
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import (
|
|
62
|
+
OTLPSpanExporter, # type: ignore
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
return OTLPSpanExporter()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _create_exporter(config: OtelConfig) -> SpanExporter:
|
|
69
|
+
if config.exporter_type == OtelExporterType.Console:
|
|
70
|
+
return _create_console_span_exporter()
|
|
71
|
+
elif config.exporter_type == OtelExporterType.Zipkin:
|
|
72
|
+
return _create_zipkin_span_exporter()
|
|
73
|
+
elif config.exporter_type == OtelExporterType.OtlpGrpc:
|
|
74
|
+
return _create_otlp_grpc_exporter()
|
|
75
|
+
elif config.exporter_type == OtelExporterType.OtlpHttp:
|
|
76
|
+
return _create_otlp_http_exporter()
|
|
77
|
+
|
|
78
|
+
raise AssertionError(f"Unsupported exporter type '{config.exporter_type}'.")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _default_service_instance_id() -> str:
|
|
82
|
+
return socket.gethostbyaddr("127.0.0.1")[0] if platform.system() == "Darwin" else socket.getfqdn()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _create_resource(config: OtelConfig) -> Resource:
|
|
86
|
+
# all PROCESS_RUNTIME_* attribute values including the code below picked as-is
|
|
87
|
+
# from recommendations written in:
|
|
88
|
+
#
|
|
89
|
+
# https://opentelemetry.io/docs/specs/semconv/resource/process/#python-runtimes
|
|
90
|
+
vinfo = sys.implementation.version
|
|
91
|
+
process_runtime_version = ".".join(
|
|
92
|
+
map(
|
|
93
|
+
str,
|
|
94
|
+
vinfo[:3] if vinfo.releaselevel == "final" and not vinfo.serial else vinfo,
|
|
95
|
+
)
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
service_instance_id = config.service_instance_id or _default_service_instance_id()
|
|
99
|
+
|
|
100
|
+
return Resource.create(
|
|
101
|
+
attributes={
|
|
102
|
+
SERVICE_NAME: config.service_name,
|
|
103
|
+
SERVICE_VERSION: __version__,
|
|
104
|
+
SERVICE_INSTANCE_ID: service_instance_id,
|
|
105
|
+
SERVICE_NAMESPACE: config.service_namespace or "",
|
|
106
|
+
OS_TYPE: platform.system().lower(),
|
|
107
|
+
OS_DESCRIPTION: platform.platform(terse=True),
|
|
108
|
+
PROCESS_PID: os.getpid(),
|
|
109
|
+
PROCESS_PARENT_PID: os.getppid(),
|
|
110
|
+
PROCESS_RUNTIME_NAME: sys.implementation.name,
|
|
111
|
+
PROCESS_RUNTIME_VERSION: process_runtime_version,
|
|
112
|
+
PROCESS_RUNTIME_DESCRIPTION: sys.version,
|
|
113
|
+
"os.version": platform.release(),
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def initialize_otel_tracing(config: Optional[OtelConfig]) -> None:
|
|
119
|
+
"""
|
|
120
|
+
Initializes OpenTelemetry tracing according to the provided `config`:
|
|
121
|
+
|
|
122
|
+
- If the config is specified, the method creates the desired exporter and
|
|
123
|
+
initializes the tracer provider to pipe traces to it
|
|
124
|
+
|
|
125
|
+
- If the config is None, the method will initialize tracer provider to
|
|
126
|
+
NoOp implementation.
|
|
127
|
+
|
|
128
|
+
:param config: server's open telemetry configuration
|
|
129
|
+
:return: None
|
|
130
|
+
"""
|
|
131
|
+
if config is None or config.exporter_type is None:
|
|
132
|
+
trace.set_tracer_provider(trace.NoOpTracerProvider())
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
resource = _create_resource(config)
|
|
136
|
+
span_exporter = _create_exporter(config)
|
|
137
|
+
|
|
138
|
+
span_processor = BatchSpanProcessor(span_exporter=span_exporter)
|
|
139
|
+
|
|
140
|
+
tracer_provider = TracerProvider(resource=resource)
|
|
141
|
+
tracer_provider.add_span_processor(span_processor=span_processor)
|
|
142
|
+
trace.set_tracer_provider(tracer_provider=tracer_provider)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright (c) 2024 GoodData Corporation
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|