İçeriğe geç

Dokümantasyon

Sıfırdan kayda geçmiş bir değişikliğe beş dakika.

Aşağıdaki .NET yolu. Node.js, Python ve Go aynı biçimi izler.

Parçalar nasıl birleşiyor

Reldavi iki yarımdan oluşur ve herhangi bir şey kurmadan önce hangisinin hangisi olduğunu bilmek işinize yarar. Bu çizimin solu sizin deponuzdaki koddur — üç paket ve yaklaşık on beş satır yapılandırma. Sağı başka bir yerde çalışır; ya bizim sunucularımızda ya da aynı compose dosyasıyla sizinkilerde, ve hiçbirini siz kurmazsınız.

SİZİN YAZDIĞINIZ YAZMADIĞINIZ Sizin SaveChanges’iniz değişmez — buraya hiçbir şey yazmazsınız Interceptor değişiklik izleyicisini okur, maskeler, asla bloklamaz Sınırlı bir tampon arka plan iş parçacığında boşaltılır Alım API’si tekrarlanan bir yığını kimliğe göre tekilleştirir Olay deposu sütunlu; müşteri ve ay bazında bölümlenmiş Panel ve sorgu API’si arama, zaman çizelgeleri, dışa aktarım, uyarılar iki saniyede bir, tek bir gzip’li yığın Üç paket. Yaklaşık on beş satır yapılandırma. Bizde barındırılır ya da aynı compose dosyasıyla kendi sunucunuzda.
Süreçten çıkan tek atlama, birkaç saniyede bir gönderilen gzip’li bir yığındır ve arka plan iş parçacığında olur. İstek yolunuzdaki hiçbir şey onu beklemez. Tasarımın tamamı bu: bir ödeme akışını yavaşlatabilen bir denetim izi, birinin er ya da geç kapatacağı bir denetim izidir.

Önce neye ihtiyacınız var

Bir alım anahtarıPanelde Ayarlar → API anahtarları’ndan; kendi sunucunuzda barındırıyorsanız reldavi key --tenant <slug> --scopes ingest. Bir kez gösterilir. appsettings.json içinde değil, yapılandırma sağlayıcınızda tutun — bu bir kimlik bilgisidir ve her olayın hangi müşteriye ait olduğuna karar veren şeydir.
Bir uç adresiBarındırılan hizmet için https://ingest.reldavi.com, ya da alım API’sini nereye yayımladıysanız orası.
.NET 8 veya üzeriSDK, .NET 8 ve .NET 10’u birlikte hedefler. Önce uygulamanızı yükseltmek zorunda değilsiniz.
Entity Framework CoreOtomatik yakalama için. EF Core olmadan da istemciyi kendiniz çağırarak olay kaydedebilirsiniz; Node.js, Python ve Go istemcileri zaten tasarım gereği böyle çalışır.

1. Kurulum

İki paket: değişiklikleri yakalayan EF Core interceptor'ı ve bunları gönderen istemci.

dotnet add package Reldavi.EntityFrameworkCore
dotnet add package Reldavi.Client
dotnet add package Reldavi.AspNetCore
SDK .NET 8 ve .NET 10'u birlikte destekler. Önce uygulamanızı yükseltmek zorunda değilsiniz.

2. Yapılandırma

İstemciyi kaydedin, interceptor'ı DbContext'inize ekleyin ve Reldavi'a mevcut kullanıcının kim olduğunu söyleyen middleware'i devreye alın. Middleware UseAuthentication'dan sonra gelir; öncesinde principal boştur ve her değişiklik kimsesiz kaydedilir.

// Program.cs
builder.Services.AddReldaviClient(options =>
{
    options.Endpoint = new Uri("https://ingest.reldavi.com");
    options.ApiKey   = builder.Configuration["Reldavi:ApiKey"]!;
});

builder.Services.AddReldaviEntityFrameworkCore(options =>
{
    options.MaskHashSecret = builder.Configuration["Reldavi:MaskSecret"];
    options.MaskProperty("Iban", MaskStrategy.PreserveLast, 4);
});

builder.Services.AddDbContext<ShopDbContext>((sp, options) => options
    .UseNpgsql(connectionString)
    .UseReldavi(sp));

builder.Services.AddReldaviHttpContext();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();
app.UseReldavi();   // after authentication

Her satır ne yapıyor

AddReldaviClientTaşıma katmanı: uç adres, anahtar, tampon boyutu ve boşaltma aralığı. SDK’daki tek ağ çağrısının sahibi olan arka plan göndericisini kaydeder.
AddReldaviEntityFrameworkCoreYakalama kuralları: maskeleme sırları ve öznitelik yerine yapılandırmayı tercih ettiğiniz maskeler. Öznitelikler ve bu, aynı işi yapar; sahibi olmadığınız bir sınıftaki özellik için bunu kullanın.
.UseReldavi(sp)Interceptor’ı tek bir DbContext’e bağlar. Servis koleksiyonuna değil bağlam seçeneklerine gelir ve IServiceProvider alan aşırı yüklemesi gerekir — parametresiz olanı hedefi çözemez; hiçbir şeyin görünmemesinin en yaygın sebebi budur.
AddReldaviHttpContextMüşterinin ve aktörün nereden geldiği: mevcut isteğin kimliği doğrulanmış principal’ı. Bir worker’da bunu atlayın ve yerine bir AuditScope itin.
app.UseReldavi()İstek başına o kapsamı açan ara katman. UseAuthentication ve UseAuthorization’dan sonra; çünkü onlardan önce principal’ın hiçbir talebi yoktur ve her değişiklik kimseye atfedilir.

3. İşaretleme

Varsayılan olarak her varlık denetlenir ve her alan kaydedilir. Öznitelikler bunu daraltır. Buradaki hiçbir şey iş mantığınızı değiştirmez.

Öznitelik
[AuditResource("shop.order")]Dışarıya görünen adı sabitler. Sınıfı sonradan yeniden adlandırsanız da kayıtlı filtreler çalışmaya devam eder.
[AuditLabel]Zaman çizelgesinde gösterilecek alan. Kayıt 91847 yerine A-1042 olarak okunur.
[AuditMask(...)]Değerin kendisi yerine izdüşümünü kaydeder — sizin sürecinizin içinde.
[AuditIgnore]Bir alanı ya da tüm varlığı denetim izinden tamamen çıkarır.
[AuditResource("shop.order")]
public sealed class Order
{
    public int Id { get; set; }

    [AuditLabel]
    public string Reference { get; set; } = "";

    public string Status { get; set; } = "Pending";

    [AuditMask(MaskStrategy.PreserveLast, 4)]
    public string CardNumber { get; set; } = "";

    [AuditIgnore]
    public string InternalNotes { get; set; } = "";
}

4. Doğrulama

Bir değişiklik kaydedin ve paneli açın. Olay birkaç saniye içinde görünür — varsayılan gönderim aralığı — ve fark ekranı yalnızca gerçekten değişen alanları gösterir.

  • Olay doğru aktörü gösteriyor mu? “anonymous” yazıyorsa middleware UseAuthentication'dan önce kayıtlıdır.
  • Maskeli alanlar izdüşümünü gösteriyor mu? Ham değer görüyorsanız öznitelik yanlış üyede demektir.
  • reldavi.events.dropped sayacı sıfır mı? Değilse tampon küçük ya da uç nokta sağlıksızdır.

Beş dakika sonra elinizde ne var

Bir kaydetme, dokunduğu her varlık için bir olay üretir. Bunlardan birinin hatta ve depoda nasıl göründüğü aşağıda — bir kez okumaya değer, çünkü sonrasında ürüne dair neredeyse her soru bu alanlardan birine dair bir sorudur.

{
  "id":            "01937f2e-9c14-7a3b-8f21-6d5e4c3b2a19",
  "occurredAt":    "2026-09-21T14:12:08.4419Z",
  "resourceType":  "shop.order",
  "resourceId":    "91847",
  "resourceLabel": "A-1042",
  "action":        "updated",
  "actor": {
    "id":    "u_4410",
    "name":  "deniz@acme.test",
    "type":  "user"
  },
  "changes": {
    "Status":     { "from": "Pending",        "to": "Approved" },
    "Total":      { "from": 1240.00,          "to": 1116.00 },
    "CardNumber": { "from": "•••• •••• •••• 4417", "to": "•••• •••• •••• 9021" }
  }
}
idUUIDv7, sizin sürecinizde üretilir. Aynı zamanda tekillik anahtarıdır: zaman aşımından sonra tekrarlanan bir yığın, geçmişinizi ikiye katlamak yerine tekilleşir.
occurredAtKaydetmenin tamamlandığı an; bizim aldığımız an değil, sizin saatiniz. Bir saat tıkanan bir kuyruk, bir olayı bir saat sonraya taşımamalıdır.
resourceType / resourceId[AuditResource] ile sabitlenen genel ad ve birincil anahtar. Sınıfı sonradan yeniden adlandırmak kayıtlı bir filtreyi bozmaz.
resourceLabel[AuditLabel] özelliği; böylece zaman çizelgesi 91847 değil A-1042 diye okunur.
actioncreated, updated, deleted — sizin beyanınızdan değil, değişiklik izleyicisinden türetilir.
actorKimin yaptığı; HTTP isteğinden çözülür. Arka plan işleri için system, değişikliği bir model yürüttüyse yanında bir agent.
changesYalnızca gerçekten değişen özellikler; her biri öncesi ve sonrasıyla. Değişmeyen bir özellik tekrarlanmaz, hiç bulunmaz.
Maskelenmiş özellikler maskelenmiş olarak gelir. Ham değer, onu üreten sürecin dışında hiç var olmamıştır — ne tamponda, ne hatta, ne depomuzda, ne de bu gövdede.

Tek bir kaydetmenin içinde ne oluyor

Kodu ilk okuyanın aklına iki soru birlikte gelir: işlemim artık daha mı yavaş, ve geri alınırsa denetim olayına ne olur? İki cevap da şu dört anın sırasında.

SavingChanges veritabanı henüz bir şey görmeden izleyiciyi oku, maskele, beklet Yazma sizin işleminiz, değişmeden burada bize ait hiçbir şey çalışmaz SavedChanges işlem başarıyla tamamlandı olayları tampona teslim et …ya da Failed geri alındı veya iptal edildi yakalanan her şeyi at Geri alınan bir kaydetme hiçbir şey yayımlamaz. Yakalanan olaylar onunla birlikte atılır.
Sizin yazmanız sırasında bize ait hiçbir şey çalışmazDeğişiklik izleyicisi okunur ve değerler, veritabanına dokunulmadan önce maskelenir. Oradan işlemin tamamlanmasına kadar olan kısım, değişmemiş hâliyle sizin işleminizdir.
Geri alınan bir kaydetme geride hiçbir şey bırakmazSaveChangesFailed de iptal de yakalanan her şeyi atar. Gerçekleşmemiş değişiklikleri kaydeden bir denetim izi, bazılarını kaçırandan kötüdür — birincisi yanlıştır, ikincisi eksik.
Interceptor kaydetmeler arasında durum tutmazEF Core, aynı seçeneklerden kurulan her bağlam için tek bir örneği paylaşır. Devam eden bir kaydetmenin durumu DbContext ile anahtarlanmış bir tabloda yaşar; farklı bağlamlardaki eşzamanlı kaydetmelerin birbirinin değişikliklerini görememesinin sebebi budur.
Teslim etmek bloklayamazTampona yazmak bloklamayan bir işlemdir. Tampon doluysa beklemek yerine yük bırakır ve reldavi.events.dropped sayacını artırır; çünkü alternatifi, ödeme akışınızın bir denetim kaydını beklemesidir.

Uygulamanız bir ASP.NET Core uygulaması değilse

AddReldaviHttpContext, müşteriyi ve aktörü mevcut HTTP isteğinden çözer. Bir worker servisi, bir konsol uygulaması veya bir mesaj tüketicisinin isteği yoktur; bunlar Reldavi’ye kimin hareket ettiğini bir kapsam iterek söyler. Gerisi — interceptor, maskeleme, yığınlama — birebir aynıdır.

// A worker, a console app, a message consumer: no request, so push a scope.
using (AuditScope.Push(new AuditContext
{
    TenantId = "acme",
    Actor    = AuditActor.Service("nightly-reconciliation"),
}))
{
    order.Status = OrderStatus.Settled;

    await db.SaveChangesAsync(cancellationToken);
}
Aktör, hesap vermekle yükümlü olandır; bir arka plan işi için bu, o sırada kaydına dokunduğu kişi değil, işin altında çalıştığı servis hesabıdır. Değişikliği bir model yürüttüyse Agent değerini de verin: aktörün yanında kaydedilir, yerine asla; çünkü “işin içinde bir insan var mıydı” sorusunun cevaplanabilir kalması gerekir.

Hiçbir şey görünmüyorsa

Boş bir panelin neredeyse tamamını dört şey açıklar; bakmaya değer sıraya göre.

Hiçbir şey yok, hata da yokInterceptor bağlanmamış. UseReldavi(sp) servis koleksiyonuna değil DbContext seçeneklerine gelir ve IServiceProvider alan aşırı yüklemesi gerekir — parametresiz olanı hedefi çözemez.
Olaylar geliyor ama aktör `anonymous`UseReldavi(), UseAuthentication()’dan önce kayıtlı. Kimlik doğrulama çalışmadan önce principal’ın hiçbir talebi yoktur, dolayısıyla her değişiklik kimseye atfedilir. UseAuthorization()’dan sonra gelmeli.
Maske olması gereken yerde ham değerÖznitelik yanlış üyede — eşlenen özellik yerine bir arka alan ya da hesaplanmış bir özellik üzerinde. Maskeleme, EF Core’un izlediği şeye uygulanır.
`reldavi.events.dropped` artıyorUç adrese ulaşılamadığı için ya da yığın boyutu yazma hızınıza göre küçük olduğu için tampon doluyor. Yanındaki reldavi.batches.failed değerine bakın: başarısızlık varsa sorun uçta, yoksa tampondadır.
Bunların hepsi, üretimde hata ayıklama günlüğü açmadan, SDK’nın yayımladığı metriklerden görülebilir. Gözlemlenebilirlik başlığı altında listelenmişlerdir.

Dokümantasyonun geri kalanı

Yukarıdaki hızlı başlangıç kaydedilmiş bir değişiklikle biter; bu, işin tamamı değil başlangıcıdır. Platformun yaptığı her şey aşağıda, konu başına bir sayfa.

Değişiklikleri yakalamak Maskeleme, yapay zekâ ajanını kaydetmek, tam yapılandırma başvurusu ve diğer dil istemcileri.
İzde arama Kendi cümlelerinizle soru kutusu, değişikliğin içine koşullar ve bir aramayı uyarıya çevirmek.
Tespit Hesap bazlı davranış temeli, iki yönde saklama sapması ve kapsam — raporlaması gereken bir üreticinin hâlâ raporladığının kanıtı.
İzi kanıtlamak Mühürleme ve doğrulama, kanıt paketleri, hukuki muhafaza, ilgili kişi başvuruları ve denetçi odası.
Erişim denetimi İzi kim okudu, bir hesabı daraltmak, gömülü görüntüleyici ve tekil oturum açma.
Reldavi’yi çalıştırmak SIEM akışı, kendi sunucunuzda barındırma, yedekleme ve geri yükleme, gözlemlenebilirlik, hız sınırları ve iki arayüz dili.

Sırada ne okunur

Bir yerde takıldınız mı?

Şema, SDK kaynakları ve mimari notların tamamı açıktır. Bir şey belirsizse, bu bizim dokümantasyonumuzdaki bir hatadır. Bize yazın.