בולנט - דברים מיוחדים...     פרוטו - בניית אתרים

Israeli ASP Organization

ארגון ה-ASP הישראלי

מאמרים/דוגמאות קוד
קישורים
ספרות
חיפוש כללי:

חפש!
כלליHTMLASPASP.NETSQLמסדי נתוניםJavaScriptXML * XSLDHTML * CSSעיצוב וגרפיקהשרתיםComponentsפרסום ושיווקקידום אתריםקופירייטינגPHP
פרסומת
דף ראשי מדורים דרושים הרשמה למועדון אודותינו צור קשר
מיקום: מאמרים ודוגמאות קוד > ASP

מערכת סטטיסטיקות לאתר - חלק ב

בחלקו הראשון של המאמר, כתבתי על הדרך להעביר את קבצי הלוג אל טבלאות ה SQL SERVER, דיברתי שם על בניית תוכנית קטנה ב VB ועל הרצת התוכנית כל יום בצורה ידנית.
הוספתי גם שבעיקרון אפשר ליצור אובייקט ACTIVEX.DLL ואתו ע"י TASK יומי של ה SQL SERVER לבצע את העברת הקובץ אל בסיס הנתונים.

אחרי מספר ימים שעבדתי עם התוכנית שכתבתי לעצמי, הגעתי למסקנה שלא מתחשק לי להריץ את זה כל יום בצורה ידנית.
אני רוצה לבוא בבוקר, לפתוח את האתר בו מצויות הסטטיסטיקות שלי ומייד לראות את כל מה שקרה אמש על האתר שלי, בלי להריץ קודם כל תוכניות כל שהן.
נוסף על כך, אין לי חשק להריץ את התוכנית מספר פעמים על כל הקבצים שהחמצתי, היות והייתי בחו"ל או בחופש ולא לייד המחשב בו נמצאת, אפליקציית ה VB שמעבירה את הקבצים מספריית ה LOGFILES בשרת, לטבלת ה LOGFILES בשרת.

שלב א: הפיכת תוכנית ה STANDART.EXE ל DLL.

פתחתי ב VB פרוייקט חדש ACTIVEX.DLL שיניתי את שם הפרוייקט ע"י בחירה ב PROJECT | PROPERTIES ל CreateLogTable. את שם דף ה CLASS שנפתח שיניתי ל clsLofFiles. (כמו במאמר הקודם, ההמלצה שלי היא להריץ פעם ראשונה DTS ידני ולשמור את הקובץ שהוא מייצר)

יצרתי REFFERENCE לאובייקט Microsoft DTSPackage Object Library

הגדרתי משתנים בתחילת ה CLASS

Public goPackageOld As New DTS.Package Public goPackage As DTS.Package2 Dim File2DTS As String, File2DTS_Name As String והגדרתי פונקציה הכוללת פרמטרים Function CreateTheFile(name1 As String, name2 As String, serverName As String) היות ורציתי להשתמש ממש באותם הקודים בתוכנית הקודמת שעשיתי ולא לשנות בה הרבה, העברתי את הנתונים מתוך הפרמטרים למשתנים הגלובאלים אותם הגדרתי קודם. File2DTS = name1 File2DTS_Name = name2 כאשר File2DTS הנו השם והמסלול של הקובץ אותו אני רוצה להעביר לבסיס הנתונים לדוגמא: C:WINNTsystem32LogFilesW3SVC1ex010825.log
וה File2DTS_Name הנו שם הטבלה החדשה אותה אני רוצה להקים בבסיס הנתונים.

את הפרמטר של השרת עליו נמצא בסיס הנתונים לא הייתי צריך להעביר למשתנה גלובאלי שכן הפניות לפרמטר הזה נעשות רק בפונקציה עצמה, בעוד שהפניות לערכים של המסלול ושם הטבלה נמצאות גם ב סאב רוטינות שמבצעות את ה DTS.
נוסף על כך בסוף הפונקציה הוספתי החזרת ערך TRUE במידה והפונקציה הצליחה.
CreateTheFile = True כל מה שהצטרכתי לעשות זה לשנות את שם השרת בתוכנית הקודמת מקוד קשיח למשתנה serverName ובעצם האובייקט היה מוכן.
קימפלתי את האובייקט, התקנתי אותו ב COM+ על השרת, והייתי מוכן לשלב הבא.

שלב ב: יצירת תוכנית ASP שתייצר טבלאות של קבצי הלוג בצורה ידנית.

נכון, המטרה הייתה לעשות את זה אוטומטי לחלוטין, אבל מה יקרה אם ב 5:00 בבוקר הסרוור לא יפעל ולא יבצע את הTASK היומי להמרת קבצי הלוג לטבלאות, ואני בכלל אהיה בפריס, ודרך האינטרנט קפה שאליו אלך, כדי לראות מה קורה בשרת שלי לא אוכל להפעיל שום תוכנית שתעביר לי את קבצי הלוג לבסיס הנתונים ולא אדע כמה גולשים ביקרו אצלי באתר, לכן החלטתי להשאיר את אופציית ההעברה הידנית פתוחה למקרי חירום. ולהרחיב אותה למצב שאוכל לבצע אותה מכל מחשב בעולם המחובר לאינטרנט ויש עליו בראוזר.

<% קבעתי קבוע גלובאלי למיקום קבצי הלוג, כמובן שהייתי יכול להכניס גם את הקלדת מיקום קבצי הלוג לתוך התוכנית. Const mypath="C:WINNTsystem32LogFilesW3SVC1" בניתי תוכנית קטנה שמשתמשת ב filesystemobject לבניית קומבו בוקס עם רשימת כל קבצי הלוג שנמצאים בספריה Dim FileSystem, folder, filecollection Set filesystem = server.CreateObject("Scripting.FileSystemObject") Set folder = filesystem.GetFolder(mypath( Set filecollection = folder.Files בניתי FORM עם רשימת הקבצים וכפתור לביצוע העברת הקובץ הנבחר %> <form action=transfer.asp method=post> <select name=selFileList> <% For Each file in filecollection Response.Write "<option value=" & file.name & ">" & file.name & "</option>" Next %> </Select> <input type =submit name =submit value="Transfer Log File"> </Form> כאשר ה SUBMIT מתבצע לאחר שנבחר ערך בקומבו בוקס התוכנית הבאה מבצעת את העברת הקבצים לטבלה. <% if request("selFileList") <> "" then תחילה מתבצעות פעולות על מחרוזת בכדי להעביר את הפרמטרים הנכונים לאובייקט retVal=cstr(request("selFileList")) fileloc="C:WINNTsystem32LogFilesW3SVC10" & retVal tablename=left(retVal,len(retVal)-4( קריאה לאובייקט CreateLogTable ולקלאס clsDTSLogfile הנמצא בתוכו אותו בניתי בשלב א Set getMakeTable = server.CreateObject("CrateLogTable.clsDTSLogfile") קריאה לפונקציה CreateTheFile כולל הפרמטרים, שם קובץ הלוג והמסלול, שם הטבלה ושם השרת עליו נמצא בסיס הנתונים xxx = getMakeTable.CreateTheFile(cstr(fileloc),cstr(tablename), cstr("Boo")) הודעה על ביצוע מוצלח של העברת הקובץ Response.Write "file " & request("selFileList") & " transferd succesfuly" end if %>

שלב ג: בניית STORED PROCEDURE שיבצע את העברת הקבצים.

כדי לבצע את העברת הקבצים בצורה אוטומטית הייתי זקוק לתוכנית אחרת שתדע להריץ את ה DLL שבניתי באופן קבוע כל יום ב 5.00 בבוקר, יש מספר דרכים לעשות את זה, אני בחרתי להשתמש ב JOB MANEGER של ה SQL Server שבתוכו אפשר לקבוע שפעולה מסוימת תתבצע כל יום, פעם בשבוע, פעם בשנה, או מתי שרוצים, בשרת.
הכוונה בפעולה מסוימת זה הרצת STORED PROCEDURE שיריץ את האובייקט לבניית ה DTS ויבנה לי טבלה שמכילה את קובץ הלוג של היום הקודם.
נוסף על כך, חשבתי, היות וזה Stored Procedure אני כבר יכול לנצל אותו לעוד כמה דברים של טיפול בטבלה לאחר שנטענה, כדוגמא הרחקת כל השורות ב LOGFILE שאינם מכילים דאטה אמיתי, שורות כמו 4 השורות הראשונות בקובץ הלוג שלפעמיים חוזרות על עצמן באמצע קובץ הלוג, למשל, כאשר נעשה אתחול לשרת, מערכת הלוגים ממשיכה את הלוג הקיים לאותו יום ומוסיפה שוב את 4 השורות הראשונות.

הגדרת הפרוצדורה והמשתנים שיועברו, כאשר כפי שתראו בהמשך אני אעביר לפרוצדורה רק את המסלול בו נמצאים קבצי הלוג + שם השרת עליו נמצא ה SQL.

CREATE PROCEDURE sp_Transfer_Log_Files @Name1 varchar(255) , @ServerName varchar(255) AS הגדרת משתנים לעבודה בתוך הפרוצדורה DECLARE @Object int DECLARE @Hresult int DECLARE @TransferDone bit DECLARE @ErrorSource varchar (255) DECLARE @ErrorDesc varchar (255) DECLARE @StrSql varchar (2000) DECLARE @strYesterday1 char(10) DECLARE @strYesterday2 char(8) DECLARE @strmonth char (2) DECLARE @strYear char (2) DECLARE @strDay char (2) DECLARE @strPath varchar (255) קביעת המשתנה @strYesterday1 עם התאריך של היום הקודם set @strYesterday1 = convert(char(10),DATEADD(day, -1, GETDATE()),103) הוצאת היום החודש והשנה מתוך המשתנה 1@strYesterday , במידה והיום או החודש קטנים מ 10 הוספת מוביל 0 לפני set @strmonth = MONTH(convert(datetime,@strYesterday1,103)) if @strmonth < 10 BEGIN set @strmonth = 0 + @strmonth END set @strDay = DAY(convert(datetime,@strYesterday1,103)) if @strDay < 10 BEGIN set @strDay = 0 + @strDay END set @strYear = RIGHT(@strYesterday1,2) יצירת המשתנה @strYesterday2 שמכיל בתוכו את שם קובץ הלוג מאתמול set @strYesterday2 = ex + @strYear + @strmonth + @strDay יצירת המשתנה @strPath המכיל את המסלול לקובץ + שם הקובץ + הסיומת .log set @strPath = @name1 + @strYesterday2 + .log בתוך SQL SERVER ישנם מספר פרוצדורות שמורות הנקראות Extended Stored Procedure פרוצדורות אלו נמצאות בבסיס הנתונים MASTER ויש להן שימושים רבים, אנחנו נשתמש בתוכנית הזאת בשלוש פרוצדורות חיצוניות
sp_OACreate משמש ליצירת אובייקטים, מקביל ל server.createObject ב ASP
sp_OAMethod משמש להעברת פרמטרים לאובייק שנוצר ע"י sp_OACreate
sp_OADestroy משמש לסגירת האובייקט, מקביל ל set obj=Nothing ב ASP

המשתנה @Hresult יחזיר פרמטרים האם התבצעה הפעולה --Create the object EXEC @Hresult=sp_OACreate CrateLogTable.clsDTSLogfile, @Object OUT --Call the objects property and return the value EXEC @Hresult=sp_OAMethod @Object,CreateTheFile,@TransferDone OUT,_ @strPath,@strYesterday2,@ServerName --Destroy the object EXEC @Hresult=sp_OADestroy @Object פרוצדורה חיצונית נוספת הנה ה sp_OAGetErrorInfo המטפלת בהודעות ERROR, אם המשתנה @Hresult קיבל ערך השונה מ 0 התבצעה שגיאה באחת משלושת הפרוצדורות הקודמות, שימוש בפרוצדורה sp_OAGetErrorInfo יאפשר לנו לקבל את תיאור השגיאה IF @Hresult <> 0 BEGIN EXEC sp_OAGetErrorInfo @Object, @ErrorSource OUT, @ErrorDesc OUT PRINT Error Occurred Calling Object: + @ErrorSource + + @ErrorDesc RETURN END כאשר האובייקט מסיים את פעולתו כזכור לכם משלב א הוא מחזיר ערך TRUE את הערך הזה מכניסים המשתנה @TransferDone ואפשר בעצם לדעת עם הפעולה של העברת הקובץ לתוך בסיס הנתונים התבצעה. IF @TransferDone = 1 BEGIN PRINT The Logfile + @strYesterday2 + was transfer correctly. END ELSE BEGIN PRINT The Logfile + @strYesterday2 + was transfer incorrectly. END מכאן והילך אפשר לבצע כל מיני פעולות על הטבלה החדשה שנוצרה בבסיס הנתונים
אחת הפעולות היא לסלק את כל הרשומות שאינן מכילות דאטה על המבקרים ונוצרו מהכותרות המוכנסות לתוך קובץ הלוג. שורות אלו יכילו בעמודה הראשונה Col001 את הערכים #Software, #Version, #Date, #Fields בעזרת משפט ה SQL הבא נוכל לנקות את הטבלה מהרשומות הללו. set @StrSql =DELETE FROM +@strYesterday2+ WHERE Col001 =#Software:_ OR Col001 = #Version: OR Col001 = #Date: OR Col001 =#Fields: exec (@StrSql) כמובן שאפשר למצוא עוד דוגמאות למה שאפשר לתקן בנתונים. דוגמא אחת, נגיד שלא מעניין אותכם כל הגישות לקבצי הגראפיקה, אז אפשר לעשות DELETE לכל הרשומות שמכילות את המילה ‘%.gif או %.jpg ועוד רעיונות כמיטב מוחיכם הקודח.

שלב ד: בניית TASK להפעלת הפרוצדורה

השלב האחרון הנו בניית התהליך שיריץ כל לילה את הפרוצדורה השמורה sp_Transfer_Log_Files שתריץ את הקלאס csDTSLogfile שנמצא בתוך הקומפוננט CrateLogTable בשעה 5:00 בבוקר ויעביר את קובץ הלוג לתוך טבלה חדשה בבסיס הנתונים.
לשם כך נפנה ל JOB MANEGER של השרת
נפתח את העץ MANEGMENT בתוך ה ENTERPRISE MANEGER של ה SQL SERVER ונבחר ב SQL Server Agent. בדרך כלל ה AGENT הנו במצב של תרדמה, כלומר אינו מופעל, יש להפעיל אותו, וגם לדאוג לכך שכל פעם שהשרת עולה גם הוא יעלה. דרך ה SERVICES ב CONTROL PANEL יש להפוך את ה SQLSERVERAGENT מהפעלה ידנית לאוטומטית.

תחת ה SQL Server Agent נבחר JOB חדש, בלשונית GENERAL ניתן לו שם חדש, בלשונית STEPS נוסיף צעד חדש שיכיל את המשפט:

excute sp_Transfer_Log_Files C:WINNTsystem32LogFilesW3SVC1, MyServer כאשר הפרמטר הראשון הנו המסלול לקובצי הלוג, והפרמטר השני הוא שם שרת ה SQL שעליו נמצא בסיס הנתונים.

בלשונית SCHUDULE נקבע כי אנחנו רוצים שהJOB יתבצע כל יום ב 5:00 בבוקר, נשמור ונסגור. וממחר ב 5:00 בבוקר יש לנו כל יום את קובץ הלוג מוגש על מגש למערכת הסטטיסטיקות שבנינו.

את ביצוע בניית ה JOB אפשר לבצע גם ע"י SQL סקריפט שנראה כך: BEGIN TRANSACTION DECLARE @JobID BINARY(16) DECLARE @ReturnCode INT SELECT @ReturnCode = 0 IF (SELECT COUNT(*) FROM msdb.dbo.syscategories WHERE name = NWeb Assistant) < 1 EXECUTE msdb.dbo.sp_add_category @name = NWeb Assistant -- Delete the job with the same name (if it exists) SELECT @JobID = job_id FROM msdb.dbo.sysjobs WHERE (name = NYesterday_logFile) IF (@JobID IS NOT NULL) BEGIN -- Check if the job is a multi-server job IF (EXISTS (SELECT * FROM msdb.dbo.sysjobservers WHERE (job_id = @JobID) AND (server_id <> 0))) BEGIN -- There is, so abort the script RAISERROR (NUnable to import job Yesterday_logFile since there is already a multi-server job with this name., 16, 1) GOTO QuitWithRollback END ELSE -- Delete the [local] job EXECUTE msdb.dbo.sp_delete_job @job_name = NYesterday_logFile SELECT @JobID = NULL END BEGIN -- Add the job EXECUTE @ReturnCode = msdb.dbo.sp_add_job @job_id = @JobID OUTPUT , @job_name = NYesterday_logFile, @owner_login_name = NBOOAdministrator, @description = NNo description available., @category_name = NWeb Assistant, @enabled = 1, @notify_level_email = 0, @notify_level_page = 0, @notify_level_netsend = 0, @notify_level_eventlog = 2, @delete_level= 0 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback -- Add the job steps EXECUTE @ReturnCode = msdb.dbo.sp_add_jobstep @job_id = @JobID, @step_id = 1, @step_name = NCreate_Log_Table, @command = Nexecute sp_Transfer_Log_Files C:WINNTsystem32LogFilesW3SVC10, Boo, @database_name = NLogFiles, @server = N, @database_user_name = N, @subsystem = NTSQL, @cmdexec_success_code = 0, @flags = 0, @retry_attempts = 0, @retry_interval = 1, @output_file_name = N, @on_success_step_id = 0, @on_success_action = 1, @on_fail_step_id = 0, @on_fail_action = 2 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback EXECUTE @ReturnCode = msdb.dbo.sp_update_job @job_id = @JobID, @start_step_id = 1 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback -- Add the job schedules EXECUTE @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id = @JobID, @name = NCreate_Log_Table, @enabled = 1, @freq_type = 4, @active_start_date = 20011001, @active_start_time = 50000, @freq_interval = 1, @freq_subday_type = 1, @freq_subday_interval = 0, @freq_relative_interval = 0, @freq_recurrence_factor = 0, @active_end_date = 99991231, @active_end_time = 235959 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback -- Add the Target Servers EXECUTE @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @JobID, @server_name = N(local) IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback END COMMIT TRANSACTION GOTO EndSave QuitWithRollback: IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION EndSave:

בהצלחה ו Happy Programming



התגובות שלכם

         
01. 28/12/2004  טל
אני מתכנת asp די מתחיל - יש לי אתר חדש ונרשמתי לחברה שנותנת ססטיסטיקות בחינם ...הבעיה שמרגע שאני צריך נתונים יותר מפורטים הם נותנים לי רק את ה 100 דפים אחרונים שנצפו ומעבר זה בתשלום . קראתי את המאמר שלך - אבל הוא ממש מסורבל ונראה לי מאד קשה לכתוב את המערכת שלך , אני חשבתי שיהיו דברים יותר פשוטים - לדוגמת מונ מבקרים שהכנתי בקלות וכדומה .


מחבר: נחום גינתרמת קושי: 3  ||  עוד לא דורגכל הזכויות שמורות ל-IAO ©

חנות לסטלן  |   מתכונים  |   חגי ישראל  |   פורטל משחקים  |   חנויות מחשבים ו-ציוד הקפי  |   מגזין מסטול לסטלן המצוי  |   קליפרים  |   גידול צמחים פרחים  |   ספא פינוק מושלם