structlog-journald, ghi log vào journald

Hôm nay mình phát hành thư viện structlog-journald v0.5.0. Thư viện này tận dụng lợi thế của journald để giúp debug hệ thống multi-tenant dễ dàng hơn. Đây là những hệ thống phục vụ nhiều khách hàng, với cách làm thông thường thì log của nhiều khách hàng sẽ trộn lẫn với nhau gây khó khăn cho việc debug. Thư viện này cho phép gắn thông tin phụ (như ID khách hàng) khi ghi log rồi sau đó khi xem log bằng journalctl có thể lọc theo thông tin phụ đó. Bằng cách đó ta có thể tập trung vào một đối tượng cụ thể để truy vết.

Minh họa:

demo

...

How to automatically deploy Python web application

Recently I saw a question from a Python fellow, how to deploy Django application without manually SSH to server and run commands. This style is single-server deployment, where you put all components, from the application code, database, to static, media files, in the same server. No Docker involves. With this deployment strategy, we will need some way to deliver new version of our app everytime new code is pushed to the "release" branch of Git repository. Here is a guide.

Why we need automation? Because it is boring to do these things by hand again and again:

  • SSH to the server, cd to the installation folder.
  • Run git pull.
  • Run commands to stop your services.
...

So sánh hệ thống kiểu của Python và TypeScript

Với hơn một nửa công việc hàng ngày là làm web, Python và JavaScript là hai ngôn ngữ mình dùng nhiều. Đây vốn là hai ngôn ngữ "kiểu động" (dynamic type), nhưng mình vẫn tận dụng hệ thống kiểu (type system) của chúng để viết như với một ngôn ngữ "kiểu tĩnh" (static type). Sau một thời gian thì mình rút ra được một số kinh nghiệm để làm việc với hai hệ này.

Thật ra, ngôn ngữ JavaScript không có ký hiệu kiểu, nên nói chính xác hơn là mình đang dùng TypeScript chứ không phải JavaScript. Trước hết, người đã làm quen với JavaScript mà được giới thiệu về TypeScript thì sẽ bật lên một câu hỏi, tại sao chúng là ngôn ngữ dynamic type thì lại mất công viết như static type làm gì. Đó là vì những ích lợi sau:

  • Giúp các công cụ kiểm tra (static analysis) như MyPy, tsc hiểu được code mình, để phát hiện được bug tiềm tàng trong những trường hợp ngách mà mình chưa test.
  • Giúp các trình soạn thảo (code editor, IDE) hiểu được biến đang có kiểu gì, để đưa ra gợi ý autocomplete đúng hơn.
...


Lập trình nhúng, Rust đã có những gì?

Rust là một ngôn ngữ hiện đại dành cho lập trình hệ thống và rất phù hợp cho việc lập trình nhúng. Nếu bạn làm trong lĩnh vực điện tử, IoT và muốn thử áp dụng Rust mà đang phân vân vì chưa biết có đủ "đồ chơi" hay chưa, có thể tham khảo bài viết dưới đây.

Ferris

Trước hết, nhắc lại những ưu điểm khiến Rust đáng để thử. Sau khi dùng Rust thì tôi thấy:

  • Giúp tăng năng suất làm việc. Sự chặt chẽ của Rust khiến lập trình viên tránh bug từ sớm, và giảm đáng kể thời gian, công sức test đi test lại. Thông thường, người lập trình nhúng hay phải nạp xuống board thường xuyên để chạy thử. Nhưng với Rust, tôi có thể viết code chay liền tù tì cả tháng mà không cần nạp xuống board. Ở AgriConnect Khi tôi bắt tay vào viết những dòng code đầu tiên của dự án thì thực ra đội điện tử chỉ mới xong bản vẽ chứ chưa làm mạch. Khi mạch thử nghiệm vừa hàn xong thì code cũng gần xong. Do làm việc từ xa nên tôi cũng không trực tiếp nạp code mà nhờ bạn khác trên văn phòng kéo code từ Git về, build, nạp, quan sát log và báo lại lỗi để tôi sửa tiếp. Tính chất này của Rust có lợi cho việc phát triển song song giữa đội phần cứng và đội lập trình.
...

Thư viện ghi log cho ứng dụng Python

Trong quá trình phát triển phần mềm, ghi log là một hoạt động quan trọng phục vụ cho người lập trình. Khi một chương trình chạy không như mong muốn, ta cần phải biết sai chỗ nào để sửa. "Ghi log" là bắt chương trình của ta "kể lại" diễn biến hoạt động của nó, giá trị của một vài biến lúc ấy, để giúp ta kiểm tra lại được chỗ nào sai.

Vậy mình thường dùng thư viện nào cho việc ghi log?

Như đã đề cập trong bài "Khởi đầu dự án Python như thế nào để thuận tiện phát triển lên", Python có một thư viện chuẩn logging, mà điểm lợi là khi các thư viện cùng dùng nó, ta có thể từ tầng ứng dụng điều chỉnh "log level" cho tầng thư viện mà không cần can thiệp vào code của thư viện ấy. Vì lẽ đó, đương nhiên các ứng dụng của mình cũng dùng logging nhưng cũng kèm thêm một số thư viện bổ trợ khác để thỏa mãn nhu cầu / sở thích cá nhân.

Một trong những nhu cầu của mình là cần màu sắc phân biệt, để truy tìm điểm cần tìm cho dễ, ít nhất là các log level cần có màu sắc khác nhau để dễ dàng lọc lựa, bỏ qua thông điệp ít quan trọng. Về khoản màu sắc thì mình ưa dùng thư viện rich. Nó thậm chí còn hơn cả mong đợi vì nó còn nhận diện và tô màu theo "kiểu dữ liệu", ví dụ dữ liệu số có màu khác, dữ liệu chuỗi, đối tượng... có màu khác.

...

Lập trình ESP32 với Rust: cập nhật firmware OTA

AgriConnect, anh em đã sử dụng Rust để lập trình firmware cho ESP32 (và cả một phần backend của nền tảng IoT). Từ hôm nay tôi sẽ bắt đầu một loạt bài nhằm giúp những đồng đội trên hành trình này. "Cập nhật firmware qua mạng (OTA / over-the-air)" là bài chia sẻ đầu tiên vì đây là chủ đề mà một trong những tác giả của esp-idf-hal đã đề nghị tôi viết.

Để có tính năng cập nhật firmware OTA, esp-if-svc đã cung cấp API rồi, nhưng còn thiếu tài liệu hướng dẫn sử dụng API, cách chuẩn bị phân vùng để sử dụng API. Bài viết này là để bổ sung chỗ thiếu đó.

(English version is here.)

Chuẩn bị phân vùng

...

Programming ESP32 with Rust: OTA firmware update

We at AgriConnect have been using Rust to develop firmware for ESP32 (and even part of our IoT platform backend). From today we start a series to help fellows on the same journey. "Over-the-air firmware update" is the first sharing because it was the topic that one of the authors of esp-idf-hal suggested me to write.

For OTA firmware update, esp-idf-svc already provides API. What it lacks is a documentation how to use the API, how to prepare partitions to use with that API. This post will complement that.

(Bản tiếng Việt ở đây.)

Prepare partition

...

PlatformIO hangs when installing packages

These days, I am back with embedded programming. At AgriConnect, we use PlatformIO to setup and build embedded projects. This time, I want to evaluate a new chip and new software framework, so I tell PlatformIO to install new packages with the command pio pkg install, but it hangs.

Turn out that it is because of network problem between Vietnamese ISP and the CDN services that PlatformIO Labs use to mirror its package repositories.

The solution is to quickly setup a temporary SOCKS proxy, and let PlatformIO tool reach those CDN through the proxy. The requirement is that you have a server that is outside Viet Nam, and you can access it via SSH. The steps is simple:

  • First, make a SSH connection to our server, activating its SOCKS proxy feature. Assume that we use port 1337 for proxy.
...

"Oxy hóa" nền tảng IoT nông nghiệp bằng Rust

Trong giới lập trình, "oxy hóa" là một cách nói vui ám chỉ việc viết lại (một phần hoặc toàn bộ) một phần mềm bằng ngôn ngữ Rust, đây là một lối chơi chữ, vì "Rust" còn có nghĩa là "rỉ sét", một hiện tượng do sự oxy hóa gây nên. Gần đây mình cũng mạnh dạn oxy hóa một phần nền tảng IoT nông nghiệp của AgriConnect.

Động lực khiến mình viết lại nền tảng IoT của AgriConnect bằng Rust là để giảm tải hệ thống, tăng cường khả năng chịu áp lực trong tương lai. Phần mềm mình đang nói đến ở đây có tên mã là "Hạt Thóc". Nghe tên khiêm tốn, nhỏ bé thôi nhưng nó vận hành theo kiểu SaaS (Software as a Service), tức một phần mềm sẽ vận hành cùng lúc nhiều trang trại khách hàng. Mỗi khách hàng sẽ có một không gian riêng khi thao tác, quản lý trang trại của mình, thậm chí có tên miền riêng, nhưng thực ra tất cả đều đang được phục vụ bởi một chương trình trên server. Phần mềm này vốn được viết bằng ngôn ngữ Python, framework Django, được chia ra nhiều thành phần, mỗi thành phần chạy dưới dạng một process, một service riêng. Trong hoàn cảnh đặc thù của "Hạt Thóc" thì thì mình không "oxy hoá" theo kiểu, viết lại một vài hàm nào đó bằng Rust, biên dịch dưới dạng thư viện, rồi dùng Python import thư viện đó, mà viết lại toàn bộ thành phần con luôn. "Hạt Thóc" có ba thành phần chính:

  • Collector: Giao tiếp để thu thập dữ liệu cảm biến, trạng thái bật tắt của các tải, và lưu vào database.
  • ControlView: Cung cấp giao diện web để người dùng vào xem dữ liệu, cấu hình trang trại, đặt lịch, hay bật tắt tải bằng tay.
  • ControlCenter: Chạy ngầm để phân tích lịch, dữ liệu cảm biến để ra lệnh bật, tắt tải, kiểm tra tình trạng bất thường và phát đi cảnh báo.
...