Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logs API: not possible to use without SDK #4319

Open
lmolkova opened this issue Nov 24, 2024 · 1 comment
Open

Logs API: not possible to use without SDK #4319

lmolkova opened this issue Nov 24, 2024 · 1 comment
Labels

Comments

@lmolkova
Copy link
Contributor

lmolkova commented Nov 24, 2024

Let's assume I'm building a logging bridge for one of many python non-standard loggers (e.g. structlog).

I should be able to create a library using logging (bridge) API alone.

So I should write a code like:

from opentelemetry._logs import get_logger_provider
from opentelemetry._logs import LogRecord as APILogRecord

logger = get_logger_provider().get_logger(__name__)

logger.emit(APILogRecord(body="Hello, World!", attributes={"foo": "bar"}))

It'd fail with

opentelemetry\sdk\_logs\_internal\export\__init__.py", line 97, in <lambda>
    formatter: Callable[[LogRecord], str] = lambda record: record.to_json()
                                                           ^^^^^^^^^^^^^^
AttributeError: 'LogRecord' object has no attribute 'to_json'

Probably related to #3552


The recommendation

  1. Make it possible to (properly) use Logs API alone without touching SDK types
  2. Add example and tests that use vanilla logs API (with note that it's for logging bridges, not end users
  3. Call API and SDK log records differently to minimize confusion. E.g. SDK one could be ReadWriteLogRecord and should probably replace LogData (see Logs SDK: consider removing LogData and extending SDK LogRecord to have instrumentation scope #4313)
  4. Consider using a pattern similar to tracing when users don't need to instantiate a new span. Instead they could call logger.emit(....) with parameters and the SDK implementation of logger will create SDK implementation of LogRecord

Part of open-telemetry/community#1751

@lmolkova
Copy link
Contributor Author

This is part of the same issue - if I try to use SDK LogRecord directly like in this snippet

from opentelemetry._logs import LogRecord as APILogRecord
from opentelemetry._logs import get_logger_provider
from opentelemetry.sdk._logs import LogRecord as SDKLogRecord

...
resource = Resource.create({"service.name": "test logs"})
logger_provider = LoggerProvider(resource=resource)
logger_provider.add_log_record_processor(SimpleLogRecordProcessor(ConsoleLogExporter()))
set_logger_provider(logger_provider)

logger = get_logger_provider().get_logger(__name__)

with trace_provider.get_tracer("example").start_as_current_span("foo"):
    logger.emit(SDKLogRecord(body="Hello, World!", attributes={"foo": "bar"}))

I get into the following issues:

  1. I have to provide timestamp even though it's optional

        formatter: Callable[[LogRecord], str] = lambda record: record.to_json()
                                                               ^^^^^^^^^^^^^^^^
      File "opentelemetry\sdk\_logs\_internal\__init__.py", line 230, in to_json
        "timestamp": ns_to_iso_str(self.timestamp),
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "opentelemetry\sdk\util\__init__.py", line 27, in ns_to_iso_str
        nanoseconds / 1e9, tz=datetime.timezone.utc
        ~~~~~~~~~~~~^~~~~
    TypeError: unsupported operand type(s) for /: 'NoneType' and 'float'
    
  2. If I provide it (logger.emit(SDKLogRecord(timestamp=time_ns(), body="Hello, World!", attributes={"foo": "bar"}))) I don't get resource attributes set

    {
        "body": "Hello, World!",
        "severity_number": "None",
        "severity_text": null,
        "attributes": {
            "foo": "bar"
        },
        "dropped_attributes": 0,
        "timestamp": "2024-11-24T19:48:29.322928Z",
        "observed_timestamp": "2024-11-24T19:48:29.322928Z",
        "trace_id": "",
        "span_id": "",
        "trace_flags": null,
        "resource": {
            "attributes": {
                "telemetry.sdk.language": "python",
                "telemetry.sdk.name": "opentelemetry",
                "telemetry.sdk.version": "1.28.2",
                "service.name": "unknown_service"
            },
            "schema_url": ""
        }
    }
  3. Also you can see that trace-context is not set despite having valid current span

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Development

No branches or pull requests

2 participants