Power BI, Power Platform, PowerShell / 23 Kasım 2022 / Miraç ÖZTÜRK
Merhabalar, iyi günler.
Bugün Microsoft’un birbirinden bağımsız veri kaynaklarınızı tutarlı, görsel olarak sürükleyici ve etkileşimli öngörülere dönüştürmenizi sağlamak için birlikte çalışan yazılım hizmetlerinden, uygulamalardan ve bağlayıcılardan oluşan bir koleksiyonu olan Power BI’ın PowerShell üzerinde rapor yedekleme ve yedek bilgi takibi hakkında neler yapılabileceğine yönelik aktarımlarda bulunmaya çalışacağım.
Şimdiden iyi okumalar.
***
Geçmiş PowerShell yazılarımızda;
- PowerShell üzerinde Power BI kullanımı, (EK)
- PowerShell üzerinden Power BI kaynakları listesi elde edilmesi, (EK)
- PowerShell üzerinden Power BI kullanıcı listesi elde edilmesi, (EK)
- PowerShell üzerinden Power BI Kullanıcı dökümleri/özetleri elde edilmesi, (EK)
- PowerShell üzerinden Power BI kullanıcı eylemleri/işlemleri elde edilmesi, (EK)
- PowerShell üzerinden Power BI mevcut kaynaklar listesi elde edilmesi, (EK)
- PowerShell üzerinden Power BI kaynaklarının çalışma durumlarının dökümleri/özetleri elde edilmesi (EK)
konularına yönelik aktarımlarda bulunmuştuk.
Bu yazıda da yönetilebilir bir sistem oluşturmaya yönelik çalışmalarımıza devam ederek;
- Mevcut raporların yedeklerini yerel çalışma alanına aktarma,
- Aktarım bilgilerini sistem üzerinde takip etme (Yedekleme bilgi takibi işlem dökümü)
konularını ele almaya çalışacağız.
Dilerseniz hızlıca önceki yazılarımızla edindiğimiz bilgiler dahilinde işlemlere başlayalım.
Kurgu olarak; Power BI üzerindeki çalışma alanlarına, oradanda ilgili rapor bilgilerine ulaşıp servis üzerinden bu bilgiler ile ilgili dosyaları yerel dizinimizde yedeklemeye çalışacağız.
Öncelikle Power BI hizmetine bağlanalım;
Connect-PowerBIServiceAccount
Dilerseniz parametrik olarakta erişimde bulunabilirsiniz.
*Görev (Task) oluşturulacak ise zorunlu olacaktır. (Önceki çalışmada belirtilmiştir, bağlantı için lütfen tıklayınız.)
Görüntülendiği gibi servise erişebiliyoruz, ikinci adım olarak ise çalışma alanlarımıza ulaşmamız gerekiyor.
Önceki çalışmalarımızdan edindiğimiz bilgiler dahilinde çalışma alanı sayısı ve listesine ulaşalım;
$Workspaces = Get-PowerBIWorkspace
$Workspaces.Count
$Workspaces.Name
Şuan çalışma alanlarına da ulaşabilir durumdayız.
Peki; genel olarak raporlarımıza ulaşmayı deneyelim;
$Reports = Get-PowerBIReport
$Reports.Count
$Reports.Name
rapor erişimimiz ile de ilgili bir problem gözükmemektedir.
Şimdide çalışma alanlarında yer alan ilgili raporlara ulaşmayı deneyelim.
Bunun için rapor erişim yönteminde; çalışma alanına ait tekil erişim değerini kullanmalıyız. (Id)
*Yani rapor erişiminde bulunurken ilgili çalışma alanına yönelik belirteçte bulunmamız gerekmektedir.
Bunu önceki yazımızda değindiğimiz; atama yöntemi ile parametrik değerimizi çalışma alanına yönelik çağırarak deneyelim;
$Report = Get-PowerBIReport -WorkspaceId $Workspaces.Id
Görüldüğü üzere raporlara ulaşabiliyoruz fakat bunu ilgili çalışma alanı altında yer alana ilgili rapora ulaşmayı deneyerek gerçekleştirmemiz gerekmektedir.
Önceki çalışmalarımız da kulladığımız döngü yöntemleri ile bunu gerçekleştirmeye çalışalım.
Yani;
foreach($workspace in $Workspaces)
{
"RAPOR SORGULAMASI"
}
formunda oluşturmaya çalışalım.
Bu format üzerinde çalışma alanı ve ilgili rapor bilgilerini parametrik olarak düzenleyip, işlemde bulunduğumuzda;
foreach($Workspace in $Workspaces)
{
$Report = Get-PowerBIReport -WorkspaceId $Workspace.Id
$Report
}
ilgili çalışma alanı altındaki rapor bilgilerinede ulaşabildiğimiz görüntülenmektedir.
Şimdi Microsoft’un sağladığı veri kaynağı yenileme geçmişi API hizmetine göz atmamız gerekmektedir.
Bağlantı: Report – Export Report
İlgili API hizmeti erişim formatı;
Export-PowerBIReport -WorkspaceId WorkspaceId -Id ReportId -OutFile DirectoryFileName
şeklindedir.
Fakat Power BI servis üzerindeki bu hizmeti tüm çalışma alanlarında yer alan raporlar için dinamik olarak kurgulamamız gerekmektedir.
Burada;
- ReportId (Rapor Id)
- Directory (Dizin)
- FileName (Dosya Adı)
gibi alanları parametrik olarak dönüştürüp kullanabiliriz.
Yani;
Export-PowerBIReport –WorkspaceId $Workspace.ID –Id $Report.ID –OutFile $OutputFile
formatında dinamik kullanılabilir bir şekle çevirmeye çalışacağız.
Öncelikle burda $OutputFile parametresini ele alalım.
Bu parametre içerisinde dosyanın kayıt edileceği alan uzantısı ve dosya adı yer almalıdır.
Bunu tekrardan parametrik olarak yapılanıdırıp, ilgili parametreye atamamız gerekmetedir.
*Tüm oluşacak sistem; parametrik olarak yönetilebilir bir yapıda olmalıdır, sanki OOP mantalitesine benzer gibi…
Peki; o zaman ana parametremiz kurgulandığında aşağıdaki formattaki gibi kullanılacak;
$OutputFile = $OutputPath + "\" + $FileName
alt parametrelerimiz ise;
$OutputPath = "C:\PowerBI_Report_BackUp\"
$FileName = $Report.name + ".pbix"
şeklinde olacak.
Burada $OutputPath bilgisi tamamen yedekleme yapacağınız ilgili dizine yöneliktir, $FileName bilgisi ise ilgili dosyanın kayıt edileceği ada/dosya adına yöneliktir.
*Bu bilgiler sisteminiz ve yönteminize göre farklılık gösterebilir.
Tabi edindiğimiz bilgiler dahilinde bu kısımda tekrar bir rapor bazlı edinimde bulunacağız.
Bunun için ek bir döngüye ihtiyaç duyacağız.
Yani yapımız;
foreach($Workspace in $Workspaces) {
"CALISMA ALANI SORGULAMASI" foreach($Report in $Reports) { "RAPOR SORGULAMASI" } }
şeklinde olacak ve düzenlendiğinde ise sorgu yapımız;
Connect-PowerBIServiceAccount
$Workspaces = Get-PowerBIWorkspace
$OutputPath = C:\PowerBI_Report_BackUp\"
foreach($Workspace in $Workspaces)
{
$Reports = Get-PowerBIReport -WorkspaceId $Workspace.Id
foreach($Report in $Reports)
{
$OutputPath = "C:\PowerBI_Report_BackUp\"
$FileName = $Report.name + ".pbix"
$OutputFile = $OutputPath + "\" + $FileName
$OutputFile
}
}
formatına dönüşecek.
Peki hızlıca çalıştırarak bir testte bulunalım;
çıktılara ait uzantıları elde edebiliyoruz fakat bir ” \ – Ters Slash” karakterini fazla yazdığımız görüntülenmektedir.
Peki; $OutputFile parametresini aşağıdaki şekilde düzenleyelim o zaman;
$OutputFile = $OutputPath + $FileName
Şimdiye kadar; Power BI servise erişip, çalışma alanları ve raporlara ulaşıp, son olarak kayıt parametrelerini oluşturmuş olduk.Şimdi ise Power BI API hizmeti ile rapor aktarımını test edelim.
Hızlıca API istemcimizi oluşturduğumuz parametrelere göre düzenleyip;
Export-PowerBIReport –WorkspaceId $Workspace.ID –Id $Report.ID –OutFile $OutputFile
çalıştıralım;
Connect-PowerBIServiceAccount $Workspaces = Get-PowerBIWorkspace $OutputPath = C:\PowerBI_Report_BackUp\" foreach($Workspace in $Workspaces) { $Reports = Get-PowerBIReport -WorkspaceId $Workspace.Id foreach($Report in $Reports) { $OutputPath = "C:\PowerBI_Report_BackUp\" $FileName = $Report.name + ".pbix" $OutputFile = $OutputPath + "\" + $FileName Export-PowerBIReport –WorkspaceId $Workspace.ID –Id $Report.ID –OutFile $OutputFile } }
hatalarla dolu bir çıktı görüntülemekteyiz.
Peki; herhangi bir dosya dizinimize aktarılmış mı, kayıt altına alınmış mı?
Evet bazı raporlar kayıt edilmiş, fakat hata verenler neler ve neden hata vermiş?
Buna çözüm oluştruması adına Microsoft’un yayınlamış olduğu dokümantasyondan Try-Catch-Finally hata kontrol yönetmini mevcut yapımıza yönelik bilgi edinimi adına kurgulayıp, uyarlayabiliriz.
*İlgili bağlantı için lütfen tıklayınız…
İlgili çözüm yapısını ise alt döngümüz altında;
try
{
"RAPOR INDIRME DENEMESI"
"BASARILI ISE" + $Report.Name + ": "+ "Başarılı"
}
catch
{
"BASARISIZ ISE"+ $Report.Name + ": "+ "Başarısız"
}
işlem sonuçlarına göre kırıp, kurgulayabiliriz.
Peki aktardığımız kurguyu mevcut kod bloğumuza uyarlayalım ve hızlıca test edelim;
Connect-PowerBIServiceAccount
$Workspaces = Get-PowerBIWorkspace
$OutputPath = C:\PowerBI_Report_BackUp\"
foreach($Workspace in $Workspaces)
{
$Reports = Get-PowerBIReport -WorkspaceId $Workspace.Id
foreach($Report in $Reports)
{
$OutputPath = "C:\PowerBI_Report_BackUp\"
$FileName = $Report.name + ".pbix"
$OutputFile = $OutputPath + "\" + $FileName
try
{
Export-PowerBIReport –WorkspaceId $Workspace.ID –Id $Report.ID –OutFile $OutputFile
$Report.Name + ": "+ "Başarılı"
}
catch
{
$Report.Name + ": "+ "Başarısız"
}
}
}
tekrardan hata dolu bir çıktı görüntülüyoruz fakat ara alanlarda ilgili rapor isimlerimiz ve işlem durumlarıda yer almaktadır.Burda başarısız olanları yakalamak için dosya indirme istemcimiz üzerinde hata yakaladığı durumları işlemsel olarak durdurup, alt bloğa atmasını sağlayabiliriz.
Bunun için istemci alanımızı alt kısımdaki gibi güncellememiz gerekmektedir;
* -EA stop; Export Activity
Export-PowerBIReport –WorkspaceId $Workspace.ID –Id $Report.ID –OutFile $OutputFile -EA stop
Peki; tekrardan düzenlediğimiz kod bloğumuzu çalıştıralım;
evet; başarısız olan işlemleride yakalamış olduk.
Buraya kadar indirme ve kayıt altına alma kurgumuzu tamamladık; peki bu noktadan sonra önceki yazılarımızda kurgulamış olduğumuz takip sistemi adına ne gibi bilgiler sağlayabiliriz?
Tekrardan MsSQL üzerine geri dönüp bu bilgileri bir veritabanı üzerindeki tabloya yazarak işlem geçmişi bilgisi oluşturabiliriz.
Peki; öncelikle hangi parametrelerin işlem geçmişinde yer alacağı ve nasıl aktarılacağını belirleyelim.
Aktarılacak olan parametreler olarak;
- DateTime (İlgili İşlem Zamanı)
- ProcessStatus (İşlem Durumu)
- Workspace (Çalışma Alanı)
- ReportName (Rapor Adı)
- ExportUser (Aktaran Kullanıcı)
- SystemUser (İlgili Sistem Kullanıcısı)
bilgileri şuanlık takip altına alınabilir.
O halde sorgumuzu parametrelerimiz dahilinde düzenleyelim.
İşlem geçmişi bilgileri adına aktarım yapacak formatımızın önizlemesi alt kısımda yer alan görseldeki gibi olacaktır;
Önizlemesinde bulunduğunuz bu blokta; “Aynı işlevi sağlayan, okunma ve kullanılma açısından sağlıklı olmayan yöntemi kullanmak ne kadar doğru?” şeklinde ilk bakışta akıllara takılan bir soru oluşmaktadır.
Bunu işlevesel olarak bir eylemi gerçekleştirmeye yönelik; eylemde bulunan yapıya dönüştürebiliriz.
Bu noktada tekrar Microsoft kaynaklarına geri dönerek Functions (Fonksiyonlar) çözümüne göz atabiliriz.
*İlgili bağlantı için lütfen tıklayınız…
İlgili çözüm yapısı;
function FonksiyonAdi
{
Param
(
[string] $PARAMETRE1,
[string] $PARAMETRE2
<#
.
.
[TIP] $PARAMETREN
.
.
#>
)
"ILGILI ISLEMLER"
}
************************************
<#FONKSIYONU CAGIRIRKEN#>
FonksiyonAdi $PARAMETRE1 $PARAMETRE2
şeklinde kurgulanmaktadır.
Peki bu çözümün bizim yapımıza uyarlaması nasıl olacak, dilerseniz hızlıca modelleyelim.
Ek olarak aktarım işlemini de fonksiyonumuzun içerisinde gerçekleştirip asgari sürede SQL Server üzerinde ki erişim süresi kullanımında bulunmak adına bağlantı erişimini kurgulayalım;
*WriteLogMsSQL adında fonksiyon oluşturalım.
function WriteLogMsSQL
{
Param
(
[string] $Workspace,
[string] $ReportName,
[string] $ProcessStatus,
[string] $ExportUser
)
$DateTime = Get-Date
$SystemUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$Connection.Open()
$insertquery="
INSERT INTO $tableName
(
[DateTime],
[ProcessStatus],
[Workspace],
[ReportName],
[ExportUser],
[SystemUser]
)
VALUES
(
'$DateTime',
'$ProcessStatus',
'$Workspace',
'$ReportName',
'$ExportUser',
'$SystemUser'
)"
$Command.CommandText = $insertquery
$Command.ExecuteNonQuery()
$Connection.Close();
}
Yanı sıra ADO.Net tanımlamalarınıda hızlıca oluşturarak ana kod bloğumuza ekleyelim;
$serverName = " SUNUCU ADINIZ "
$databaseName = " ILGILI VERITABANI "
$tableName = " ILGILI TABLO "
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "server='$serverName';database='$databaseName';trusted_connection=true;"
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
Fonksiyona göndereceğimiz parametreler ise;
*Önceki yazılarımızda yer alan otomasyon mantığımızdaki gömülü kullanıcı giriş bilgisi olan $PBIAdminUPN.
WriteLogMsSQL $Workspace.name $Report.Name $ProcessStatus $PBIAdminUPN
şeklinde olacaktır.
MsSQL tarafındaki işlem geçmişi veri bilgilerini kayıt altına alacak tablomuz ise;
*Bireysel SQL formatı görünümü.
USE [PowerBIServiceLog]
GO
/****** Object: Table [dbo].[ReportExportLog] Script Date: 23.11.2022 10:29:48 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[ReportExportLog](
[DateTime] [datetime] NULL,
[ProcessStatus] [nvarchar](50) NULL,
[Workspace] [nvarchar](150) NULL,
[ReportName] [nvarchar](150) NULL,
[ExportUser] [nvarchar](150) NULL,
[SystemUser] [nvarchar](150) NULL
) ON [PRIMARY]
GO
formatında olacaktır.
Son olarak Try-Catch öncesinde $OutputFile parametremizde bilgi olup-olmadığını kontrol edip işleme geçişte bulunalım;
if (Test-Path $OutputFile) { Remove-Item $OutputFile }
Tüm bilgilerimizi derleyip kod bloğumuzu yeniden yapılandırdığımızda;
$PBIAdminUPN=" ERISIMI OLAN ORGANIZASYON YONETICI KULLANICINIZ " $PBIAdminPW =" ORGANIZASYON YONETICI KULLANICISI PAROLANIZ " $Security = ConvertTo-SecureString $PBIAdminPW -AsPlainText -Force $Credential = New-Object System.Management.Automation.PSCredential($PBIAdminUPN,$Security) Connect-PowerBIServiceAccount -Credential $Credential $serverName = " SUNUCU ADINIZ " $databaseName = " ILGILI VERITABANI " $tableName = " ILGILI TABLO " $Connection = New-Object System.Data.SQLClient.SQLConnection $Connection.ConnectionString = "server='$serverName';database='$databaseName';trusted_connection=true;" $Command = New-Object System.Data.SQLClient.SQLCommand $Command.Connection = $Connection $OutputPath = "C:\PowerBI_Report_BackUp\" $Workspaces = Get-PowerBIWorkspace foreach($Workspace in $Workspaces) { $Reports = Get-PowerBIReport –WorkspaceId $Workspace.Id #$Reports foreach($Report in $Reports) { $OutputPath = "C:\PowerBI_Report_BackUp\" $FileName = $Report.name + ".pbix" $OutputFile = $OutputPath + $FileName if (Test-Path $OutputFile) { Remove-Item $OutputFile } try { Export-PowerBIReport –WorkspaceId $Workspace.ID –Id $Report.ID –OutFile $OutputFile -ea stop $Report.Name + ": "+ "Başarılı" WriteLogMsSQL $Workspace.name $Report.Name $ProcessStatus $PBIAdminUPN } catch { $Report.Name + ": "+ "Başarısız" WriteLogMsSQL $Workspace.name $Report.Name $ProcessStatus $PBIAdminUPN } } } function WriteLogMsSQL { Param ( [string] $Workspace, [string] $ReportName, [string] $ProcessStatus, [string] $ExportUser ) $DateTime = Get-Date $SystemUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name $Connection.Open() $insertquery=" INSERT INTO $tableName ( [DateTime], [ProcessStatus], [Workspace], [ReportName], [ExportUser], [SystemUser] ) VALUES ( '$DateTime', '$ProcessStatus', '$Workspace', '$ReportName', '$ExportUser', '$SystemUser' )" $Command.CommandText = $insertquery $Command.ExecuteNonQuery() $Connection.Close(); } Disconnect-PowerBIServiceAccount
görüntüsünü elde etmekteyiz.
Herşey hazır olduğuna göre ana PowerShell kod ekranımıza dönüp ilgili kodumuzu çalıştıralım;
Önceki yazılarımızdan aşina olduğumuz herbir log kaydı için 1’lerin olduğu bir çıktı görüntülüyoruz.
Peki MsSQL üzerindeki tablomuza dönecek olursak;
işlem geçmişi bilgilerimizin kayıt altına alındığını görüntülüyoruz.
Dilerseniz hızlıaca yedekleme dosyamıza da göz atalım;
Genel önizlemeler dahilinde mevcut raporlarımızın ve işlem geçmişi bilgilerinin kayıt altına alınmış olduğunu görüntülemekteyiz.
Burada unutulmaması gereken ise bu kayıtların genel olarak alındığıdır. (Hepsi)
Sorgulama kısmına çeşitli kıstaslar belirleyip ilgili alanlara ya da ilgili kullanıcı erişimindeki raporlara erişebilirsiniz.
Sonrasında ise bu formatı bir System Task (Sistem Görevi) üzerinde periyordik olarak (Aylık gibi.) çalıştırdığınızda hep ilgili aysonu günü (önerilir) mevcut raporları ve işlem bilgilerini sisteme aktarıyor olacaktır.
Bugün; PowerShell üzerinde Power BI organizasyonda yer alan raporların yedeklenmesi ve yedek bilgi takibi işlem dökümlerine yönelik bilgilere ulaşmaya çalıştık.
Bir sonraki PowerShell yazımızda/yazılarımızda;
- Hata Çıktıları,
- Veri Kaynağı Yenilemesi,
- Kullanıcı Erişim Bilgileri (Yetkileri)
gibi başlıkları ele alıp, ek işlemlerde bulunuyor olacağız.
Tüm işlemlere yönelik kod dökümünü;
https://github.com/miracozturk17/PowerShellQueryChallenge
bağlantısı üzerinden elde edebilirsiniz.
Gelecek yazılarda görüşmek üzere.
İyi çalışmalar…