Lewati ke isi

Tambah Pelacakan Manual

Geser, catat, dan lacak

Berikut adalah contoh sederhana menggunakan Logfire:

import time

import logfire

logfire.configure()

with logfire.span('This is a span'):
    time.sleep(1)
    logfire.info('This is an info log')
    time.sleep(2)

Jika Anda menjalankan ini, itu harus mencetak sesuatu seperti ini:

Logfire project URL: https://logfire.pydantic.dev/my_username/my_project_name
21:02:55.078 This is a span
21:02:56.084   This is an info log

URL proyek pembukaan harus menampilkan yang berikut ini dalam tampilan Langsung:

Contoh sederhana dalam tampilan langsung

Kotak biru dengan 1+ menunjukkan bahwa bentang berisi 1 anak langsung. Klik kotak untuk memperluas bentang untuk menampilkan anak-anaknya:

Contoh sederhana dalam tampilan langsung dengan rentang terbuka

Harap dicatat:

  1. Setiap bentang atau log yang dibuat dalam blok with logfire.span(...): akan menjadi anak dari rentang itu. Ini memungkinkan Anda untuk mengatur kayu gelondongan Anda dengan baik di pohon terstruktur. Anda juga dapat melihat hubungan orang tua-anak ini dalam log konsol berbasis indent.

  2. Rentang memiliki waktu mulai dan waktu akhir, dan karena itu durasi. Rentang ini membutuhkan waktu 3 detik untuk menyelesaikannya.

  3. Untuk log, waktu mulai dan akhir sama, sehingga tidak memiliki durasi. Namun, Anda masih dapat melihat di UI bahwa log dibuat 1 detik setelah rentang dimulai dan 2 detik sebelum rentang berakhir.

Jika Anda mengklik tautan "Jelajahi" di bilah navigasi atas, Anda dapat menulis SQL untuk menjelajah lebih lanjut, misalnya:

Query in Explore view: pilih ekstrak ('detik' dari end _ timestamp - start _ timestamp) sebagai durasi, jenis, pesan, trace _ id, span _ id, parent _ span _ id dari catatan yang dipesan oleh start _ timestamp

Perhatian:

  1. Spanduk dan log disimpan bersama dalam tabel 记录 yang sama.

  2. Log 的parent_span_id adalah rentang span_id.

  3. Keduanya memiliki trace_id yang sama. Anda dapat mengkliknya untuk membuka tab baru di tampilan "langsung," yang telah disaring ke_trace_itu.

_trace_adalah pohon bentang / batang kayu yang memiliki akar yang sama. Setiap kali bentang / batang kayu baru dibuat tanpa bentang aktif, jejak baru dibuat. Jika itu adalah bentang, setiap keturunan dari bentang itu akan menjadi bagian dari jejak yang sama. Untuk mengatur log dengan baik ke dalam jejak, yang terbaik adalah membuat rentang di tingkat atas untuk mewakili operasi lanjutan, seperti memproses permintaan server web.

atribut

Bentang dan log dapat ditambahkan dengan data terstruktur, seperti:

logfire.info ('Halo', nama = 'Dunia')

Jika Anda mengklik log "Halo" di Live View, Anda akan melihat yang berikut di panel detail di sebelah kanan:

Atribut nama dalam Tampilan langsung

Data ini disimpan dalam format JSON di kolom 属性 tabel 记录. Misalnya, Anda dapat menggunakan attributes->>'name' = 'world' dalam filter SQL di bagian atas tampilan langsung untuk hanya menampilkan log ini. Ini digunakan sebagai klausa WHERE dari kueri SQL pada tabel 记录.

Baik bentang maupun log dapat memiliki sifat yang mengandung nilai arbitrer yang secara cerdas diserialisasikan ke JSON sesuai kebutuhan. Anda dapat menyampaikan argumen kata kunci apa pun untuk mengatur properti selama tidak dimulai dengan garis bawah (_). Namespace ini dicadangkan untuk parameter kata kunci tambahan dengan makna spesifik logfire.

Terkadang berguna untuk melampirkan properti ke ruang lingkup setelah dibuat tetapi sebelum selesai. Anda dapat melakukannya dengan memanggil metode span.set_attribute:

with logfire.span('Calculating...') as span:
    result = 1 + 2
    span.set_attribute('result', result)

Nama pesan dan rentang

Jika Anda menjalankan kode ini:

import logfire

logfire.configure()

for name in ['Alice', 'Bob', 'Carol']:
    logfire.info('Hello {name}', name=name)

Query in Explore view: pilih span _ name, attributes- > > 'name' sebagai name, pesan dari record yang dipesan oleh start _ timestamp

Di sini Anda dapat melihat:

  1. Argumen pertama,“Hello {name}”, menjadi nilai kolom span_name. Anda dapat menggunakannya untuk menemukan semua catatan dari kode yang sama, meskipun pesannya berbeda, misalnya menggunakan span_name = 'Hello {name}' filter SQL.

  2. Nama span juga digunakan sebagai template bergaya str.format yang diformat dengan properti untuk menghasilkan kolom 消息. Pesan ditampilkan di log konsol dan dalam tampilan langsung.

Anda juga dapat mengatur span.message setelah rentang dimulai tetapi sebelum rentang selesai, misalnya:

with logfire.span('Calculating...') as span:
    result = 1 + 2
    span.message = f'Calculated: {result}'

Anda dapat menggunakan 消息 untuk menyaring catatan terkait, seperti “Hello%”之类的消息, tetapi menyaring kolom span_name lebih efisien karena diindeks. Sekali lagi, menggunakan span_name = 'Hello {name}' 和 attributes->>'name' = 'Alice' lebih baik daripada menggunakan message = 'Hello Alice'.

Agar dapat menyaring catatan terkait secara efektif,_kardinalitas_dari nama rentang harus rendah, yang berarti mereka tidak boleh terlalu bervariasi. Misalnya, ini akan buruk:

name = get_username()
logfire.info('Hello ' + name, name=name)

Karena sekarang kolom span_name akan memiliki nilai yang berbeda untuk setiap nama pengguna. Tapi tidak apa-apa:

Karena kolom span_name sekarang hanya memiliki dua nilai ('Goodbye {name}' dan 'Hello {name}'), penyaringan span_name = 'Hello {name}' lebih mudah dan lebih efisien daripada penyaringan span_name = '{word} {name}' 和 attributes->>'word' = 'Hello'.

Jika Anda ingin nama rentang berbeda dari templat pesan, Anda dapat menggunakan parameter _span_name, misalnya:

word = 'Goodbye' if leaving else 'Hello'
logfire.info(word + ' {name}', name=name)

Ini mengatur span_name ke “Hello” dan 消息 ke “Hello world”。 Perhatikan bahwa parameter _span_name dimulai dengan garis bawah untuk membedakannya dari properti.

logfire.info('Hello {name}', name='world', _span_name='Hello')

senar-f


Sebagai gantinya:

logfire.info('Hello {name}', name=name)

Jauh lebih nyaman menggunakan S-String untuk menghindari pengulangan NAME tiga kali:

logfire.info(f'Hello {name}')

Berlawanan dengan bagian sebelumnya, ini ada di Python 3.11 +_efek_Bagus, karena Logfire akan menggunakan sihir khusus untuk span_name Setel ke “Hello {name}” Dan akan name Properti diatur ke name Nilai variabel, sehingga setara dengan cuplikan kode sebelumnya. Inilah yang perlu Anda ketahui:

  • Fitur ini diaktifkan secara default pada Python 3.11 +. Anda dapat menonaktifkannya menggunakan [logfire.configure(inspect_arguments=False) ][logfire.configure(inspect_arguments)]. Anda juga dapat mengaktifkannya dalam Python 3.9 dan 3.10, tetapi kemungkinan besar tidak berfungsi dengan baik.

  • Dalam keadaan normal, parameter pemeriksaan harus selalu valid. Penting untuk dicatat bahwa kode sumber harus tersedia, jadi, misalnya, menyebarkan hanya file .pyc yang akan menyebabkannya gagal.

  • Jika memeriksa parameter gagal, Anda akan menerima peringatan, dan parameter s-string akan digunakan sebagai template pemformatan. Ini berarti Anda akan mendapatkan nama rentang kardinalitas yang tinggi, seperti “Hello Alice”, dan tidak ada atribut 名称, tetapi informasinya tidak akan sepenuhnya hilang.

  • Jika memeriksa parameter diaktifkan, parameter akan diperiksa apakah string f digunakan atau tidak. Jadi jika Anda menulis logfire.info('Hello {name}', name=name) dan memeriksa parameter gagal, Anda masih akan mendapatkan peringatan.

  • Nilai dalam s-string kembali dievaluasi dan diformat oleh Logfire. Ini berarti bahwa jika get_username()(atau konversi string dari apa pun yang dikembalikan) mahal atau memiliki efek samping, Anda harus menghindari penggunaan kode seperti logfire.info(f'Hello {get_username()}').

  • Argumen pertama harus menjadi string f yang sebenarnya.logfire.info(f'Hello {name}') akan bekerja, tetapi message = f'Hello {name}'; logfire.info(message) tidak, dan juga tidak akan logfire.info('Hello ' + name).

  • Parameter pemeriksaan di-cache sehingga pemeriksaan berulang dari string f yang sama memiliki kinerja minimal di atas kepala. Namun, mengurai file sumber besar menimbulkan overhead yang signifikan saat memeriksa parameter untuk pertama kalinya. Either way, menghindari overhead ini memerlukan menonaktifkan parameter pemeriksaan sepenuhnya, tidak hanya menghindari senar f.

abnormal

logfire.span Manajer konteks akan secara otomatis mencatat pengecualian apa pun yang menyebabkannya keluar, seperti:

import logfire

logfire.configure()

with logfire.span('This is a span'):
    raise ValueError('This is an error')

Jika Anda mengklik Spans di Live View, akan ada tab "Exception Traceback" di panel kanan:

Traceback di UI

Pengecualian yang ditangkap tetapi tidak dibaca ulang tidak akan dicatat, misalnya:

with logfire.span('This is a span'):
    try:
        raise ValueError('This is an acceptable error not worth recording')
    except ValueError:
        pass

Jika Anda ingin mencatat pengecualian yang ditangani, gunakan span.record_exception Metode:

with logfire.span('This is a span') as span:
    try:
        raise ValueError('Catch this error, but record it')
    except ValueError as e:
        span.record_exception(e)

Atau, jika Anda hanya ingin mencatat pengecualian tanpa membuat bentang untuk kasus normal, Anda dapat menggunakan logfire.exception :

try:
    raise ValueError('This is an error')
except ValueError:
    logfire.exception('Something went wrong')

logfire.exception(...) setara dengan logfire.error(..., _exc_info=True)。. Jika Anda ingin mencatat tracebacks tingkat non-error, Anda juga dapat menggunakan _exc_info dengan metode logging lainnya. Jika objek pengecualian bukan yang sedang diproses, Anda dapat mengatur _exc_info sebagai objek pengecualian. Jangan lupa garis bawah di depan!

Rentang fungsional yang nyaman dengan @logfire.instrument

Biasanya, Anda ingin membungkus seluruh fungsi dalam rentang. Alih-alih melakukan ini:

def my_function(x, y):
    with logfire.span('my_function', x=x, y=y):
        ...

Anda dapat menggunakan dekorator @logfire.instrument :

Secara default, ini menambahkan parameter fungsi sebagai properti ke bentang. Untuk menonaktifkan fitur ini (misalnya, jika parameter adalah objek besar yang tidak layak untuk dikumpulkan), gunakan instrument(extract_args=False)。

Nama rentang default mirip dengan Calling module_name.my_function Anda dapat memberikan nama rentang alternatif sebagai argumen pertama untuk instrument Bahkan dapat diformat sebagai argumen untuk template, seperti:

@logfire.instrument('Applying my_function to {x=} and {y=}')
def my_function(x, y):
    ...

my_function(3, 4)
# Logs: Applying my_function to x=3 and y=4

Perhatian

  • '@ Logfire.instrumental' Dekorator harus diterapkan terlebih dahulu, yaitu, di bawah dekorator lainnya.
  • Kode sumber suatu fungsi harus dapat diakses.

tingkat log

Metode untuk membuat berbagai tingkat log adalah sebagai berikut:

  • logfire.trace
  • logfire.debug
  • logfire.info
  • logfire.notice(日志火灾通知)
  • logfire.warn
  • logfire.error
  • logfire.fatal

Secara default, log 跟踪 dan 调试 disembunyikan. Anda dapat mengubah pengaturan ini dengan mengklik menu drop-down "Default Level" di Live View:

Penurunan tingkat default

Anda juga dapat menggunakan logfire.configure untuk mengatur level minimum untuk konsol logging, seperti:

import logfire

logfire.configure(console=logfire.ConsoleOptions(min_log_level='debug'))

Untuk mencatat pesan dengan tingkat variabel, Anda dapat menggunakan logfire.log, mis.logfire.log('info', 'This is an info log') setara dengan logfire.info('This is an info log')。

Secara default, bentang adalah level 信息. Anda dapat mengubah parameter ini dengan parameter _level, misalnya 使用 logfire.span('This is a debug span', _level='debug'):. Anda juga dapat mengubah level dengan span.set_level setelah rentang dimulai tetapi sebelum rentang selesai. LogfireSpan. set _ level], misalnya:

with logfire.span('Doing a thing') as span:
    success = do_thing()
    if not success:
        span.set_level('error')

Dalam tampilan "real-time,"Rentang diwarnai sesuai dengan peringkat tertinggi dan keturunannyaMisalnya, kode berikut:

import logfire

logfire.configure()

with logfire.span('Outer span'):
    with logfire.span('Inner span'):
        logfire.info('This is an info message')
        logfire.error('This is an error message')

Ini akan muncul seperti ini:

Rentang diwarnai berdasarkan level

Di sini, tingkat bentang itu sendiri masih diatur ke informasi 默认, tetapi warnanya merah, bukan biru karena mengandung log kesalahan.

Jika bentang berakhir dengan pengecualian yang tidak tertangani, tingkat log bentang juga diatur ke 错误 selain mencatat jejak belakang seperti yang dijelaskan di atas. Ini tidak terjadi ketika menggunakan metode span.record_exception . Metode LogfireSpan.record _ exception].

Dalam database, level log disimpan sebagai angka dalam kolom 级别. Nilai-nilai ini didasarkan pada OpenTelemetry, mis.info adalah 9. Anda dapat menggunakan fungsi SQL level_num untuk mengubah nama level menjadi angka, mis.级别 > level_num('info') akan mencari semua catatan "pengecualian." Anda juga dapat menggunakan fungsi level_name SQL untuk mengonversi angka ke nama, seperti SELECT level_name(level)、... untuk melihat level yang dapat dibaca manusia dalam tampilan "Jelajahi." Perhatikan bahwa kolom level diindeks, jadi penyaringan untuk level = level_num('error') valid, tetapi penyaringan untuk level_name(level) = 'error' tidak.


本文总阅读量次