Skip to content

Commit 49a86f9

Browse files
tushar00jainfacebook-github-bot
authored andcommitted
add opentelemetry (#274)
Summary: Pull Request resolved: #274 setup otel for structured logging Reviewed By: d4l3k Differential Revision: D83289159 fbshipit-source-id: 33f1e6a740852addb0cad4c542f695f83fb25245
1 parent 39b6a2f commit 49a86f9

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ classifiers = [
1313
dynamic = ["version"]
1414
readme = "README.md"
1515
dependencies = [
16-
"torch>=2.7"
16+
"torch>=2.7",
17+
"opentelemetry-exporter-otlp-proto-http>=1.37.0",
18+
"opentelemetry-sdk>=1.37.0",
19+
"opentelemetry-api>=1.37.0",
1720
]
1821

1922
[project.urls]

torchft/otel.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import json
2+
import logging
3+
import os
4+
import time
5+
from typing import List, Sequence
6+
7+
from opentelemetry._logs import set_logger_provider
8+
9+
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
10+
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
11+
from opentelemetry.sdk._logs._internal import LogData
12+
from opentelemetry.sdk._logs.export import (
13+
BatchLogRecordProcessor,
14+
ConsoleLogExporter,
15+
LogExporter,
16+
)
17+
from opentelemetry.sdk.resources import Resource
18+
19+
_LOGGER_PROVIDER: LoggerProvider | None = None
20+
# Path to the file containing OTEL resource attributes
21+
TORCHFT_OTEL_RESOURCE_ATTRIBUTES_JSON = "TORCHFT_OTEL_RESOURCE_ATTRIBUTES_JSON"
22+
23+
24+
class TeeLogExporter(LogExporter):
25+
"""Exporter that writes to multiple exporters."""
26+
27+
def __init__(
28+
self,
29+
exporters: List[LogExporter],
30+
) -> None:
31+
self._exporters = exporters
32+
33+
def export(self, batch: Sequence[LogData]) -> None:
34+
for e in self._exporters:
35+
e.export(batch)
36+
37+
def shutdown(self) -> None:
38+
for e in self._exporters:
39+
e.shutdown()
40+
41+
42+
def setup_logger() -> None:
43+
torchft_otel_resource_attributes_json = os.environ.get(
44+
TORCHFT_OTEL_RESOURCE_ATTRIBUTES_JSON
45+
)
46+
47+
if torchft_otel_resource_attributes_json is not None:
48+
with open(torchft_otel_resource_attributes_json) as f:
49+
attributes = json.loads(f.read())
50+
resource = Resource.create(attributes=attributes)
51+
else:
52+
resource = Resource.create()
53+
54+
logger_provider = LoggerProvider(resource=resource)
55+
set_logger_provider(logger_provider)
56+
57+
exporter = TeeLogExporter(
58+
exporters=[
59+
ConsoleLogExporter(),
60+
OTLPLogExporter(
61+
timeout=5,
62+
),
63+
],
64+
)
65+
logger_provider.add_log_record_processor(BatchLogRecordProcessor(exporter))
66+
handler = LoggingHandler(level=logging.NOTSET, logger_provider=logger_provider)
67+
68+
logging.getLogger().setLevel(logging.NOTSET)
69+
70+
# Attach OTLP handler to root logger
71+
logging.getLogger().addHandler(handler)
72+
73+
global _LOGGER_PROVIDER
74+
_LOGGER_PROVIDER = logger_provider
75+
76+
77+
def shutdown() -> None:
78+
assert _LOGGER_PROVIDER is not None
79+
_LOGGER_PROVIDER.shutdown()
80+
81+
82+
# Example usage of the logger
83+
def main() -> None:
84+
setup_logger()
85+
86+
while True:
87+
time.sleep(1)
88+
logging.debug(
89+
"Quick zephyrs blow, vexing daft Jim.",
90+
extra={
91+
"test_attr": "value1",
92+
},
93+
)
94+
logging.info("Jackdaws love my big sphinx of quartz.")
95+
96+
# Create different namespaced logger
97+
logger = logging.getLogger("myapp.area1")
98+
99+
logger.debug(
100+
"Quick zephyrs blow, vexing daft Jim.",
101+
extra={
102+
"test_attr": "value2",
103+
},
104+
)
105+
logger.info("How quickly daft jumping zebras vex.")
106+
107+
print("Example done; exiting...")
108+
109+
110+
if __name__ == "__main__":
111+
main()

0 commit comments

Comments
 (0)