22
loading...
This website collects cookies to deliver better user experience
import logging
logger = logging.getLogger("Basic Logger")
logger.info("This is a log message")
logger.critical("This a second log message")
import logging
logger = logging.getLogger("Basic Logger")
logger.setLevel(logging.INFO)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)
logger.addHandler(stream_handler)
file_handler = logging.FileHandler("error.log")
file_handler.setLevel(logging.ERROR)
logger.addHandler(file_handler)
logger.info("This is a log message")
logger.critical("This a second log message")
StreamHandler()
will output all messages above INFO level to our terminal, while the FileHandler()
will write all ERROR level and above messages to the error.log
file.if status == "departed":
logger.info(f"{flight['airline']} flight {flight['id']} from {flight['origin']['airport']}, {flight['origin']['city']}, {flight['origin']['country']} ({flight['origin']['iata']}) to {flight['destination']['airport']}, {flight['destination']['city']}, {flight['destination']['country']} ({flight['destination']['iata']}) has departed at {flight['flight_time']}")
if status == 'landed':
logger.info(f"{flight['airline']} flight {flight['id']} from {flight['origin']['airport']}, {flight['origin']['city']}, {flight['origin']['country']} ({flight['origin']['iata']}) to {flight['destination']['airport']}, {flight['destination']['city']}, {flight['destination']['country']} ({flight['destination']['iata']}) has landed at {flight['flight_time']}")
if status == 'delayed':
logger.warning(f"{flight['airline']} flight {flight['id']} from {flight['origin']['airport']}, {flight['origin']['city']}, {flight['origin']['country']} ({flight['origin']['iata']}) to {flight['destination']['airport']}, {flight['destination']['city']}, {flight['destination']['country']} ({flight['destination']['iata']}) is delayed by approximately {flight['delay_duration']}")
if status == 'cancelled':
logger.critical(f"{flight['airline']} flight {flight['id']} from {flight['origin']['airport']}, {flight['origin']['city']}, {flight['origin']['country']} ({flight['origin']['iata']}) to {flight['destination']['airport']}, {flight['destination']['city']}, {flight['destination']['country']} ({flight['destination']['iata']}) has been cancelled due to {flight['cancellation_reason']}")
> WARNING:__main__:Air New Zealand flight 533 from El Alto International airport, La Paz, Bolivia (LPB) to Wenzhou airport, Wenzhou, China (WNZ) is delayed by approximately 5 hours, 22 minutes
> INFO:__main__:Tianjin Airlines flight 839 from Pinto Martins International airport, Fortaleza, Brazil (FOR) to Puerto del Rosario airport, Antigua, Spain (FUE) has departed at 12:29:17
I believe the widespread use of format strings in logging is
based on two presumptions: The first level consumer of a log message is a human. The programmer knows what information is needed to debug an issue. I believe these presumptions are no longer correct in server-side software.
Paul Querna
from structlog import get_logger
log = get_logger("Structured Logger")
if status in ['departed', 'landed']:
log.info(status, **flight)
elif status == 'delayed':
log.warning(status, **flight)
else:
log.critical(status, **flight)
> 2021-08-27 12:45.54 [warning ] delayed airline=Tropic Air delay_duration=35634 destination={'airport': 'San Pedro airport', 'iata': 'SPR', 'icao': '', 'city': 'San Pedro', 'state': 'Belize', 'country': 'Belize'} flight_id=597 origin={'airport': 'Mingaladon airport', 'iata': 'RGN', 'icao': 'VYYY', 'city': 'Insein', 'state': 'Yangon', 'country': 'Myanmar'} price=563 stops=3
> {"flight_id": 715, "airline": "Skymark Airlines", "origin": {"airport": "Cheju International airport", "iata": "CJU", "icao": "RKPC", "city": "Jeju-Si", "state": "Jaeju-Do", "country": "South Korea"}, "destination": {"airport": "Viracopos International airport", "iata": "VCP", "icao": "SBKP", "city": "Campinas", "state": "Sao Paulo", "country": "Brazil"}, "stops": 3, "price": 474, "cancellation_reason": "mechanical fault", "event": "cancelled", "logger": "Structured Logger", "level": "critical", "timestamp": "2021-08-27T17:03:05.786801Z"}
def send_to_newrelic(logger, log_method, event_dict):
headers = {
'Api-Key': os.environ['API_KEY']
}
payload = {
"message": f"{logger} - {log_method} - {event_dict['event']}",
"attributes": event_dict
}
httpx.post('https://log-api.newrelic.com/log/v1', json=payload, headers=headers)
return event_dict
import os
import httpx
import structlog
from structlog import get_logger
log = get_logger("Structured Logger")
# Custom processor
# Uses the New Relic Log API
# https://docs.newrelic.com/docs/logs/log-management/log-api/introduction-log-api/
def send_to_newrelic(logger, log_method, event_dict):
# Your New Relic API Key
# https://docs.newrelic.com/docs/apis/intro-apis/new-relic-api-keys/
headers = {"Api-Key": os.environ["API_KEY"]}
# Our log message and all the event context is sent as a JSON string
# in the POST body
# https://docs.newrelic.com/docs/logs/log-management/log-api/introduction-log-api/#json-content
payload = {
"message": f"{log_method} - {event_dict['event']}",
"attributes": event_dict,
}
httpx.post("https://log-api.newrelic.com/log/v1", json=payload, headers=headers)
return event_dict
# Configure Structlog's processor pipeline
structlog.configure(
processors=[send_to_newrelic, structlog.processors.JSONRenderer()],
)
# Your application code that
# is generating the data to be logged
flight = get_flight_details()
status = get_flight_status()
# Generate our log events
if status in ["departed", "landed"]:
log.info(status, **flight)
elif status == "delayed":
log.warning(status, **flight)
else:
log.critical(status, **flight)
`SELECT count(*) FROM Log WHERE `airline` = 'Air Canada'
AND `event` = 'cancelled' AND `cancellation_reason` LIKE
'%mechanical%'`
`SELECT count(*) FROM Log WHERE `origin.iata` = 'PDX' AND
`event` = 'delayed' AND `delay_duration` > 60*60`
`SELECT count(*) FROM Log WHERE `destination.iata` = 'AMS'
AND `origin.country` = 'United States' AND `event` =
'landed'`