-
Learning python & Backend Engineering, with Mani! Youtube: https://www.youtube.com/@GitOverHere Github: https://github.com/ManiMozaffar Linkedin: https://www.linkedin.com/in/manimozaffar Admin: @Mani_nikou لینک گروه: https://t.me/PythonFellow
یک کامنتی گذاشتن که ظاهرا سو بداشت شده بود از حرفه من،
من نگفتم کسی که فعالیت گیتهاب نداره حتما رد فلگه. گفتم میتونه رد فلگ باشه. قطعا به عوامل دیگه هم بستگی داره.
و فعال بودن گیتهاب به این منظور نیست که پروفایل شما سبزه سبز باشه. ممکنه شما سالی ۵ تا ایشو بزنید و هیچ فعالیت دیگه ای نداشته باشین، ولی همون ۵ تا ایشو رو تو ابزار هایی که استفاده کردین ازش زدید و خیلی قشنگ مشکل رو توضیح دادید. این خیلی اسکیلارو میتونه نشون بده به کسی که داره رزومتون رو میبینه. این بنظره من بیشتر ارزش داره تا اینکه صرفا پروفایلتون سبز باشه. هدف رنگی کردن پروفایل نیست
@PyBackendHub
#واقعی دیدم chatgpt داون شده. رفتم پیج استتوسش. نوشته رفرش کنید درست میشه. 😂
- کار نمیکنه این چرا؟
+رفرش کن درست میشه
@PyBackendHub
داشتم docker compose مینوشتم که یک مشکلی داشتم (رو مخم بود مشکل نبود واقعا:)) ) و اونم این بود که وقتی دارم YAML مینوسیم خیلی خودمو دارم تکرار میکنم. مثلا endpoint های opentelemtry ام رو باید به همه service هام بدم.
بنابراین اینطوری میشه:
services:
foo_service:
environment:
trace_endpoint: baz_url
log_endpoint: baz2_url
metric_endpoint: baz3_url
# some other env....
bar_service:
environment:
trace_endpoint: baz_url
log_endpoint: baz2_url
metric_endpoint: baz3_url
# some other env...
x-otel-endpoints: &default-otel-endpoints
trace_endpoint: baz_url
log_endpoint: baz2_url
metric_endpoint: baz3_url
services:
foo_service:
environment:
<<: *default-otel-endpoints
# some other env
baz_service:
environment:
<<: *default-otel-endpoints
# some other env
یک پارادیم که خیلی قشنگه بدونید راجبش CoC هست.
Convention over configuration
این پارادیم core خیلی از فریم ورک هایی هست که شما استفاده میکنی. و خیلی خوبه که خودت هم استفاده کنی.
حالا این پارادیم چیه؟
این پارادیم خیلی سادست. میگه تعداد تصمیم هایی که یک برنامه نویس قراره بگیره وقتی داره از یک component شما استفاده میکنه باید تو کمترین حالت ممکن باشه. یعنی چی؟
یعنی من دارم لایبری pydantic مینویسم. دیدین احتمالا که یک Field داره که شما توضیح میدی تو Field یک سری متا دیتا میدی راجب اون فیلد تو اون دیتا کلس. این فیلد کلی پارامتر میگیره. ولی همه این پارامتر ها آپشناله. و این دقیقا CoC هست. یعنی به شما این flexibility خیلی زیاد رو میده که رفتار یک component رو هرچقدر میخواین تغییر بدید, در عین حال کلی مقدار دیفالت میذاره براتون که لازم نباشه خیلی فکر کنید و تصمیم های زیادی بگیرین.
این اصل رو شما هرجایی میتونید استفاده کنید. چه تو backend چه فرانت چه devops چه هر جای دیگه ای.
@PyBackendHub
چقدر یک architecture میتونه پیچیده باشه؟
Sentry: YES
احساس میکنم این پیچیدگی از قصده که نخوای خودت maintain کنی اینو 😂 چون هزینه maintain کردنش به صورت self host از هزینه اینکه از نسخه کلادش استفاده کنی بیشتره :))
هنوز متوجه نمیشم چرا هم memcached هست هم ردیس. 😁
@PyBackendHub
درود دوستان
مصاحبه سطح جونیور با آقا بهداد عزیز
سری جدید ماک اینترویو رو داریم شروع میکنیم و لطفا در این فرآیند هرگونه نظر مثبت و منفی دارین برام بنویسین که توی مصاحبه های بعد تغییر بدیم
@BenDevelop
https://www.youtube.com/watch?v=DJ6lHSp7gUo
سید تو کامنت اشاره کرد, چند تا راه حل داره.
یک راه حلی که من قبلا استفاده میکردم و خیلی بهینه نیست اینه که شما برنچ فیچرت رو ریست کنی رو آخرین کامیتی که رو برنچ پروداکشنم هست. و بهت هاتفیکس رو cherry pick کنی و همه کامیت های بعدیشم هم چری پیک کنید (میتونید یک رنجی از کامیت هارو چری پیک کنید نیازی نیست دونه دونه انجام بدید). و بعد کامیت هایی که زده بودید هم چری پیک کنید.برای هر برنچ ۵-۱۰ دقیقه طول میکشه و خیلی بهینه نیست.
راه حل خیلی منطقی تر استفاده از git rerere هست. این قابلیت رو میده که اگه کانفلیکت مشابهی رو یک بار حل کردین دیگه دفعات بعدی هم حل شه. این اسم مخفف Reuse Recorded Resolution هست, که خیلی معنی قشنگی داره. جوری که حلش میکنی اینه که شما وقتی یک کانفلیکت رو حل میکنی گیت راهکار شما رو ذخیره میکنه و یادش میمونه و دفعه بعدی که بخواین دقیقا همون کانفلیکت رو حل کنید git براتون حل میکنه.
یک یوزکیسش دیگش اینه که شما رو یک برنچی زمان زیادی کار کردی و الان اون برنچ خیلی کانفلیکت خورده. اصلا نیازی نیست کانفلیکت هارو حل کنید چون احتمالا قبلا حل کردیشون.
porteneuve/fix-conflicts-only-once-with-git-rerere-7d116b2cec67">لینک یک مقاله که کامل توضیحش داده
لینک خود داکیومنتش
@PyBackendHub
ریسپانس API وقتی tasks رو صدا میزنید.
از همین ID هم میتونید استفاده کنید برای اینکه تسک رو بلافاصله اجرا کنید و دیگه منتظر اون trigger بعدیش نباشین (مثلا اگه قراره فردا ساعت ۹ اجرا شه دوباره)
@PyBackendHub
در این کنفرانس، دو آزمایش انجام شد. در آزمایش اول، یک تفنگ پینتبال روی یک شاسی روبهروی یک تابلو قرار داده شد و در هر لحظه، یک توپ پینتبال به سمت تابلو پرتاب میشد و در نهایت تصویر یک آدمک مصور شد.
آزمایش دوم تقریبا شبیه به آزمایش اول بود با این تفاوت که اینبار بجای یک تفنگ پینتبال، ۱،۱۰۰ مازل پینتبال با فشار هوای موجود در چهار محفظه به حجم کلی ۸،۰۰۰ لیتر به سمت تابلو پرتاب میشدن.
آزمایش اول نمایانگر شیوه عملکرد CPU و آزمایش دوم شبیهساز شیوه عملکرد GPU بود. اگه به آزمایش اول دقت کنید، میبینید که مجری صحنه با دستکاری تفنگ، سرعت پرتاب توپ رو تغییر میده. طی کنفرانس به این عمل مجری هیچ اشارهای نمیشه اما این پارامتر در CPU، کلاک (Clock) پردازنده نامیده میشه که با یکای هرتز اندازهگیری و مشخص میشه که به معنی سرعت CPU در پردازش هر تسک طی یک ثانیه (سیکل زمانی) هست.
مثلا یک پردازنده ۳ گیگاهرتزی (3GHz) نمایانگر اینه که این پردازنده این قابلیت رو داره که در هر ثانیه، ۳ میلیارد بار بین هر تسک پردازشی سوییچ کنه! تسک پردازشی میتونه خواندن از مموری، نوشتن در IO، باز کردن یک سشن وب یا هرچیزی باشه.
وظیفه پردازش در پردازنده بر عهده هسته (Core) هست. یک خصیصه بد هستهها، Lazy بودنشونه. خیلی زود به خواب میرن. فرض کنید شما دوتا تسک دارید.
تسک اول: بررسی تعداد اعداد اول بین عدد ۱ میلیارد تا ۲ میلیارد.
تسک دوم: ۲۰ بار پرینت کردن Hello world.
از اونجا که ترتیب انجام این تسکها مهم نیستن، پس اهمیتی هم نداره که کدوم زودتر انجام شه. مسلما تسک دوم در کسری از ثانیه اجرا میشه اما تسک اول خیلی زمانبره ولی شما برنامه رو طوری مینویسید که ابتدا تسک اول و سپس تسک دوم اجرا شه. یک هسته شروع میکنه تعداد اعداد اول بین یک میلیارد و دو میلیارد رو میشماره و شما تا الان تقریبا چند دقیقهای هست که منتظرید تا یکی از این دو تسک تموم شه.
این درحالیه که میتونستید برای پردازنده مشخص کنید که برنامه شما از دو تسک تشکیل شده که کاملا مستقل و مجزا هستن نسبت به هم تا هسته میتونست برنامه رو به نحو بهتری اجرا کنه. این عمل اجرای موازی نام داره. درواقع شما دارید برنامه رو به دو بخش (ترد) تقسیم میکنید و دست Core رو واسه سوییچ کردن بین هریک از این تسکها باز میذارید.
درسته که گفتیم تسک دوم خیلی سادهتر و سریعتر اجرا میشه، ولی این یکم ناعادلانه هست اگه هسته، زمان بیشتری رو اختصاص بده به اجرای تسک اول تا تسک دوم. توی پایتون، این زمان بصورت پیشفرض بر روی ۰.۰۰۵ تنظیم شده. یعنی هسته فقط میتونه ۵ هزارم ثانیه به هر تسک اجازه اجرا شدن بده. اگه فکر میکنید این عدد خیلی کوچیکه، سرعت سوییچ کردن پردازنده در ثانیه رو فراموش نکنید.
python -c "import sys; print(sys.getswitchinterval())"
0.005
zoxide is a smarter cd command, inspired by z and autojump.It remembers which directories you use most frequently, so you can "jump" to them in just a few keystrokes. zoxide works on all major shells.
https://github.com/ajeetdsouza/zoxide
این خیلی چیزه تمیزیه👌 یک سالی میشه تقریبا دارمش رو سیستمم. مخصوصا الان خیلی بدرد بخوره. مثلا یک پروژه داشتم اسمش helicopter بود. نمیتونستم پیداش کنم. میخواستم cd کنم تو دایرکتوریش.
z helicopter
یک پستی دیدم تو لینکدین و یک چیزیه که حقیقتا خیلی مخالفشم. نظره شما چیه؟ مصاحبه کننده میاد از قبل یک سوالی آماده میکنه, و یک جوابی تو ذهنش داره. اگه شما دقیقا همون جواب تو ذهن مصاحبه کننده رو بدی قبولی. و اگه ندی قبول نیستی.
بنظرم این مدل مصاحبه بدترین مصاحبه هست. اصلا شبیه دنیای واقعی نیست. هدف مصاحبه این نیست که شما به جواب درست برسی. هدف اینه که یک نفر بیاد و بتونیم باهم یک مشکلی رو حل کنیم با هم فکری. سوالی که فقط ۱ جواب داره سوال خوبی نیست. تو دنیای واقعی یک سولوشن نداریم بلکه ترید آف داریم.
@PyBackendHub
در نهایت تو داشبورد همچین حالتی میشه اگه روش ۳ام رو برین:
@PyBacknedHub
توصیه شخصی, دیدم بعضیا میخوان یک فریم ورک یا زبون جدید یاد بگیرن خیلی سریع میرن سراغ یک پروژه خیلی خوب. (از جمله خودم تا چند وقت پیش). ولی حقیقتا خیلی کمکتون نمیکنه.مثلا من برم یک پروژه خفن FastAPI ببینم و سعی کنم همون پترن رو تکرار کنم. چه مشکلی ایجاد میکنه؟ دید منو به شدت کور و محدود میکنه. یعنی چی؟ فرض کنید شما کاناله منو دارین دنبال میکنید, یک پروژه فست دارین میخواین تصمیم بگیرین چطور با دیتابیس کانکت شید. خب راه های مختلفی هست, مثل استفاده از orm و چه orm ای هم مهمه. یک راه حل اینه که شما صرفا چیزی که من نوشتم رو دنبال کنید, که اصلا ممکنه حرف من درست نباشه یا دیدم bias باشه.
خب چیکار باید کنیم؟ نظره من اینه که شما باید بتونید سبک سنگین کنید. ببینید کسی که از orm django استفاده کرده چی گفته (تو اینترنت مقاله پیدا کنید). درک کنید چرا یک نفر از orm django خوشش میاد و یک نفر بدش میاد. همینکارو برای بقیه orm های پایتونی هم انجام بدید. و البته یک قدم خارج تر شید. فلسفه استفاده orm چیه؟ چه فلسفه ای پشت orm django هست؟ چه فلسفه ای پشت sqlalchemy هست؟ query builder چیه؟ فرقش چیه با orm؟ یعنی خیلی فلسفه ها صرفا تو طرز استفاده از ابزاره, نه تنوع یا فیچر های مختلف یک ابزار.
@PyBackendHub
این بدترین طرز فکریه که یک نفر میتونه داشته باشه، اینکه یک سری الاف (علاف؟) تو گیتهاب مجانی دارن کد میزنن. جدا از اینکه اون سری افراد چه درآمدی دارن که مهم نیست، اصلا طرز فکر اشتباهه.
سوال من اینه که شما مگه از یک ابزار اوپن سورس استفاده نمیکنی؟ کمترین contribution ای که میتونی داشته باشی اینه که اگه مشکلی میبینی تو اون ابزار، یک ایشو براش بذاری. این دیگه کمترین حالته.
همین مشکلم ممکنه خودت حل کنی. میتونی با شرکت هماهنگ کنی و همونو PR بدی بشی contributer.
و در نهایت این پروموشنی هست برای خودتون. من همین چند وقت با اینکه اصلا تمایلی نداشتم شرکتمو عوض کنم، ولی ۲ شرکت پروژه aioclock من رو دیده بودن خوششون اومد، و لطف کردن منو به مصاحبه دعوت کردن.(منظورم recruiter نیست)
خلاصه کسی که پروفایل گیتهابش مثل برف سفیده، بنظرم میتونه رد فلگ باشه!
@PyBackendHub
یک چیزی که من خیلی زیاد میبینم مخصوصا تو community خودمون اینه که اکثر مواقع سوال ها بدون context پرسیده میشن. و این context خیلی میتونه تو جواب سوال تاثیر داشته باشه. بذارین مثال بزنم:
سلام من میخوام پایتون یاد بگیرم. میشه بهم ۵ تا کتاب معرفی کنید؟
اوکی تخصصتون چیه؟بک اند کار میکنید؟ ML؟ دوآپسین و دنبال یک زبون اسکریپتی هستین؟ دیتا اینجینر هستین؟ از پایتون چه یوزکیسی دارین؟! چقدر الان بلدین؟ چیا بلدین؟ این رو جواب سوال تاثیر میذاره. ممکنه جواب رو ۱۸۰ درجه بچرخونه. مثلا یک مثال دیگه.
سلام من از playwright یا سلنیوم استفاده میکنم. میخوام یک element رو سلکت کنم. بنظرتون از چه سلکتوری استفاده کنم؟css selector یا xpath یا .. ؟
اگه QA باشین, من میگم css selector بهتره. با پراپرتی test-id تو html که اصلا برای همین کار خلق شده. چرا؟ چون خودتون HTML رو کنترل میکنید و به فرانت میتونید بگین تغییر بده.
ولی اگه دارین اسکرپ میکنید یک سایتی رو, اون موقع xpath selector بهتره. چون احتمال تغییر یک element صفحه html ای که خودتون کنترل میکنید با xpath خیلی کمتره تا با سلکتور. مثلا اگه فرانت از Material UI استفاده میکنه اصلا استفاده از سلکتور خیلی سخت تر میشه. ولی شما با xpath میتونید query های خیلی پیشرفته و پیچیده تری بنویسید. مثلا رو دکمه ای که داخل متنش "login" هست کلیک کن! این query همیشه جواب میده تا زمانی که design ux صفحه کلا تغییر کنه.
پس همیشه بنظرم وقتی سوال میپرسین کامل context بدید. اشکال نداره سوالتون ۴-۵ خط طولانی تر شه ولی جواب درست تری دریافت خواهید کرد.
@PyBackendHub
یک مشکلی همیشه تو تستا وجود داره وقتی دارین از container استفاده میکنید
اینم اونه که container پورت میگیره. تستون به یک سری hostname و پورت دپندنسی داره و اینا خیلی راحت میتونن باهم conflict بخورن.
و خیلیمشکلات دیگه
و خیلیوقتا ماک یا استفاده از SQLite پاسخگو نیاز نیست مثلا ماگریشن دارین یا functionality خاصی از دیتابیس استفاده میکنید یا … و تستاتون flaky میشه
اکثر این مشکلات رو testcontainer حلشون کرده.
https://testcontainers.com/
@PyBackendHub
اگه ری اکت کار میکنید یک سری بزنید به این پروژه:
https://www.locatorjs.com/
کارش اینه که شما رو component ای که تو صفحه مرورگرت میبینی کلیک میکنی و میبرتت تو کد دقیقا قسمت مربوط بهش.😅👌
@PyBackendHub
یک پلی لیست عالی از امیربهادر 👌
دیدن ماک یکی از بهترین روش های یادگیریه.
مصاحبه انجام دادن مثل رزومه نوشتن یک اسکیله. لزوما کسی که دانش تکنیکال خوبی داره خوب مصاحبه نمیکنه. بخش خیلی زیادی از مصاحبه اسکیل communication هست که خیلی مهمه. لزوما کسی که بره تو یک مصاحبه ۳ تا سوال الگوریتمی حل کنه استخدام نمیشه و FAANG و شرکت های بزرگ تر برای اینکه فرصت چک کردن assignment ندارن و هزینه زیادی براشون میبره و لایو هم نیست رو به پرسیدن سوال های الگوریتمی آوردن, که البته هدفشون استخدام یک leet coder نیست(ولی سولوشن بهتری براشون وجود نداره یا هنوز پیدا نشده که بتونن یک سوالی رو طرح کنند و طرف بتونه با کد زدن حلش کنه و اسکیل communication اش هم نشون بده و عمق دانشش هم نشون بده)
و البته سوالای system design ای که میپرسن هم دوباره یک مکانیزمه که leet coder ای استخدام نکنن که communication خوبی هم داره.
من میخواستم خیلی وقت پیش یک repo بنویسم برای مصاحبه دادن (مثل رزومه نویسی)
ولی بعدش فهمیدم که اونقدر مصاحبه objective نیست و تا کسی مصاحبه ماک خوب نبینه چند تا مصاحبه نده قلقش دستش نمیاد. ولی نوشتن resume خیلی آبجکتیو هست که یک ریپو دارم در خصوص تکنیک های نوشتن رزومه.
یک نکته که اخیرا کشف کردم برای اپلای, اگه سطح زبانتون خوبه حتما درج کنید (مثلا اگه c1 هستین بنویسید که c1 هستین) چون واقعا خیلیا (حتی اروپایی و خارجی ها) خیلی خوب حرف نمیزنن. البته دروغ ننویسید چون قطعا باعث ریجکتتون میشه اگه بنویسید c1 بلدید ولی تو مصاحبه اول نتونید در حد c1 حرف بزنید.
@PyBackendHub
ما یک git flow داریم، که شاید اسمشو نشنیده باشین ولی حتما احتمال زیاد همینو رعایت میکنید. تو عکس توضیح داده. تو پروژه واقعی main میشه پروداکشن، و جای release branches میشه staging و develop هم که میشه نسخه dev که معمولا خیلی استیبل نیست.
معمولا وقتی هاتفیکس انجام میدین رو پروداکشن، رو برنچ staging و dev باید rebase کنید.
حالا سوال دارم ازتون، فکر کنید هات فیکس انجام دادید، ولیبخاطر اون هاتفیکس برنچ develop کانفلیکت خورد موقع ریبیس که حل کردین. ولی شما ۱۰۰ تا برنچ فیچر دیگه دارین از develop، که حالا همشون دقیقا همون کانفلیکت رو خوردن. بنظرتون راهکارش چیه؟
@PyBackendHub
نسخه ۰.۱.۰ فریم ورک AioClock منتشر شد 🔥🔥
آیوکلاک یک فریم ورک برای scheduling هست که کاملا Async عه و هر چیزی که یک فریم ورک نیاز داره رو داخلش داره, مثل دپندسی اینجکشن و startup/stop ایونت و ...
تغییرات نسخه جدید:
- بهبود داکیومنت و خوانایی بسیار بالا
- اضافه شدن پلاگین FastAPI - تو لایه HTTP میتونید ببینید چه تسک هایی دارین, که قراره ران بشن و اگه لازم بود یک تسک با درخواست POST همون لحظه ران کنید!
- اضافه شدن API Internal - برای کنترل لایبری, و نوشتن پلاگین FastAPI که میتونید ابزار CLI باهاش بنویسید یا مثل پلاگین فست رو برای فریم ورک های وب دیگه استفاده کنید.
Github
Documentation
برای حمایت خوشحال میشم استار بدید یا contribute کنید.
@PyBackendHub
من mkdocs تاحالا کار نکرده بودم
ولی وقتی کار کردم فهمیدم چقدر راحت میتونید داک جنریت کنید. مستقیم از کد. یک عالمه پلاگین مفید داره و پلاگین نوشتن براش هم خیلی سادست.
نمونه پروژه aioclock رو میتونید ببینید که از داک استرینگ خوده سورس داکیومنت نوشتم:
خوده پروژه
داک پروژه
برای پروژه ای که مونولیتیک هست خیلی چیزه خوبی میتونه باشه حتی تو کیس بیزنس (نه لزوما اوپن سورس) چون همیشه این مشکل رو داشتم که داکیومنت وقتی تو نوشن نگه میداری خیلی زود outdate میشه و خیلی غیر منطقی هست که داکیومنت مربوط به کد رو بخوای تو نوشن بذاری.
از طرفی داک استرینگ بنویسی ممکنه تو نگاه اول مشخص نباشه و طرف باید بدونه بره سراغ چی. و سرچ کردن و اینا یکم سخت تره.
@PyBackendHub
یک نکته بگم که احساس میکنم اکثرا که سوال اینطوری طرح میکنن به دنبال تقلید از شرکت های بزرگ و Faang هستن. من خودم حقیقتا به یک شرکت نسبتا بزرگ پارسال مصاحبه داشتم و تو مصاحبه سوال الگوریتمی رو به کند ترین روش ممکن حل کردم ولی پاس داده شدم مرحله بعد و فیدبکی که گرفتم این بود که مهم نیست اگه اینو به صورت آپتیمایز ترین حالت ممکن حل کنی. مهم ارتباط گرفتن موقع حل سواله و اینکه آگاه باشی از ترید آف. کلا دنبال این هستن که طرز فکر شما رو ببینن. و یک سوال الگوریتمی لایو کدینگ کم هزینه ترین کار برای این موضوع هست (که شاید بهترین عملکرد رو نداشته باشه ولی خب شرکت Faang کلی کاندید داره....)
تو کیس بالا خیلیا به روشی حل کرده بودن که حالت <ایده آل>از دیده مصاحبه کننده نبود و تقلب بود. ولی بنظره من اتفاقا خیلی با ارزش تره. وقتی من سولوشنی میدم که کلا out of box بوده و داره نیاز بیزنس من رو پوشش میده چرا که نه؟
@PyBackendHub
یادتونه دیشب مثال زدم که میتونید query بزنید؟به این شکل الان میشه زد. خیلی راحت.
و شما میتونید به این شکل خیلی راحت observability رو داشته باشین
پی نوشت: از لاگ فایر استفاده نکردم چون هنوز نه span link داره نه Context Propagation
@PyBackendHub
#otel
نمونه مثال دیروز رو یادتونه؟ پیاده سازیش همچین حالتی میشه. که البته کدشم پوش کردم اینجا که ببینید
وقتی مفاهمیشو بلد باشین خیلی سادست. مثل این میمونه SQL بلد باشین و بخواین از orm فقط برین ببینید چطوری میتونید اون query رو بنویسید. ولی اگه مفاهیم یا specification رو بلد نباشین به شدت گیج کنندست.
برای مثالمون ۳ تا راهکار هست:
۱. وقتی تو یک سرویس هستن, اگه همون کانتکس منیجری که من باز کردم رو دو بار زیر هم باز کنید اسپن دوم میشه child اسپن اول. وقتی مناسبه که تو یک سرویس نیاز دارین به چند اسپن.(دارین چند تا کار میکنید)
۲. وقتی تو دو سرویس جدا هستین, میتونید لینک کنید. برای لینک کردن باید trace id و span id رو داشته باشین. میتونید تو هدر بفرستین و بعد بگیرین.
۳. روش سوم و از همه بهتر Context Propagation هست. که اینجا مثالشو گذاشته که با ۲ تا api فلسک اینکارو انجام داده. وقتی به درد میخوره که شما یک event ای دارین تو چند تا سرویس. و میخواین همه باهم کنار هم بیان. یک وقتا حتی ممکنه sequential هم نباشن. ولی پیچیده تره این حالت. برای همین تو مثال نیاوردمش. تو کیس ما این روش از بهترین بود.
@PyBackendHub
#otel
تو پست قبلی که ریپلای زدم به زبون خیلی ساده توضیح دادم opentelemetry یا همون otel چیه. در ادامه سری پست های opentelemetry (که مخففش میشه otel) میپردازیم به ۴ تا component بسیار مهم که بدنه otel رو تشکیل میدن. همونطور که گفتم otel صرفا یک specification ای هست برای observation. پس خیلی مهمه که بدونید. این component ها چی هستن و چرا وجود دارن.
اولی که حتما آشنایی دارین باهاش لاگه. که زیادی به توضیح نمیخواد. لاگ قدیمی ترین شکل observation در یک نرم افزار بود. دومی event هست. event هم لاگه ولی با این تفاوت که event کاملا structure مشخصی داره. تو otel لاگ قابل قبول نیست و همیشه باید event بسازین. معمولا پکیج های otel خودکار لاگ شما رو تبدیل به event میکنن پس نیازی نیست نگرانش باشی. یک نمونه ساده از event اینطوریه:
{"event":"Failed to connect to DB","level":"warning","timestamp":"2024-02-15T12:45:32.681868Z","logger":"foo_module"}
ایونت به عبارت ساده تر لاگیه که تایم استمپ داره و راحت تر query میشه.
قسمت سوم otel میشه span. چیه دقیقا و فرقش با لاگ (یا ایونت چیه)؟ span یک نقطه استارت و یک نقطه انتها دارن تو زمان. یعنی تو یک بازه زمانی هستن. و هر span کلی event میتونه داشته باشه.
یعنی به عبارت ساده تر لاگ یا event درواقع یک عکسی هست از یک لحظه از execution در نرم افزار شما. ولی span یک فیلم ۳ بعدیه از یک کاری که در نرم افزار شما انجام شده. و نکته جالب تر اینه که span میتونه key attribute داشته باشه. مثلا من یک span دارم که وقتی کاربر محصولی اضافه کرد, یک مدل train شده باید اطلاعات رو از اون عکس محصول extract کنه و به محصول اضافه کنه (مثل رنگ و اینا).
تو این کیس منطقیه که اسم span من باشه "extracting metadata from product" . و attribute ای داشته باشم به اسم image_id که بدونم داره رو چه عکسی این اتفاق میفته. user_id هم مناسبه چون میدونم عکس برای چه یوزریه. تعداد تگ هایی که مثلا extract شده هم میتونم key value کنم. "extracted_tags". این شد یک span خیلی با ارزش. این مثالو تا اینجا داشته باشین.
و در آخر trace رو داریم. که مجموعه ای از span ها میشن یک trace. هر کدوم از این اسپن ها میتونن تو یک سرویس و یک جای مختلف سیستمتون اتفاق افتاده باشن. لزوما نیازی نیست این اسپن ها به ترتیب باشن. میتونن همزمان اتفاق افتاده باشن که میشه end-to-end view از سیستمتون. بخوام ساده تر بگم trace در نهایت میشه یک سریالی که چند فیلم 3d کنار هم گذاشتین و همه اینا به هم مربوطن و باهم معنی پیدا میکنن.
حالا به چه دردی میخوره؟ فکر کنید تو facebook marketplace دارین کار میکنید. و همون flow ای که بالا تر توضیح دادم هست. یوزر عکس یک محصولی رو آپلود میکنه به یک api ای. و بعد متا دیتا اون عکس extract میشه و در نهایت به عده ای از کاربران که علاقه دارن به اون category از اون محصول ایمیل ارسال میشه که مثلا همچین محصولی تو مارکت فیسبوک اومده.
به شما تیکت میدن که چرا فلان یوزر عکسش هیچ تگی نداشته؟ شما بلافاصله داشبوردتون رو query میکنید
name = 'extracting metadata from product' AND user_id='x' AND extracted_tags=0
تو خیلی زبونا ما تایپی داریم به نام Never از جمله پایتون. به چه دردی میخوره این تایپ؟
خیلی مفیده. و یکی از قشنگ ترین کاربردش exhaustive block هست. یعنی به شما اجازه اجازه میده که کدتون رو تو کیس های مختلف تو یک بلاک هندل کنید بدون اینکه چیزی رو جا بذارین. و اگه یک چیزی بعدا اضافه کردن که هندل نکرده بودین تایپ چکر ایراد بگیره ازتون و بتونید هندل کنید. مثلا فکر کنید شما User status دارین. و رفتار سیستم شما تغییر میکنه نسبه به وضعیت یوزر. و این رفتار تو تک تک بیزنس کیس ها وجود داره. یک راهش استفاده از دیزاین پترنه که به قول مارتین به نحوی کل لاجیکتون تو یک فایل باشه.و برای هر وضعیت هندلر داشته باشین. ولی یک راه خیلی آسونتر استفاده از تایپ Never هست. که خیلی قابل اعتماد تره و فضایی نمیذاره برای خطا کردن!
class UserStatus(StrEnum):
Verified = auto()
Unverified = auto()
Banned = auto()
# any other...
user_status: UserStatus
match user_status:
case UserStatus.Banned:
# handle here
...
case _:
assert_never(user_status)
enum UserStatus {
Verified,
Unverified,
Banned
}
const user_status: UserStatus
switch(user_status) {
case UserStatus.Banned:
// handle here...
default:
user_status satisfies never;
}