ورود

View Full Version : ثبت Log File



dkhatibi
دوشنبه 21 آبان 1386, 20:45 عصر
برای یک برنامه باید وقایع رخ داده توسط کاربران را ثبت کنم. چه وقایعی مهمند. در نظر من درج حذف و ویرایش و ورود و حروج کاربران هست! نظر سما چیه؟
نجوه ی ذخیره سازی. نظر من استفاده از یک جدول شامل نام کاربر و کد ویرایش شده و نام جدول به همراه تاریح هست
آیا چیزهای دیگه باید ثبت بشن؟

بانک من MsSqlServer200 .می شه از Logهای اون راحت بهره برد و زحمت زیادی نکشید؟

پرواز
دوشنبه 21 آبان 1386, 21:00 عصر
این موضوع تو بخش SQL Server بحث شده و نتایج جالبی هم بدست اومده.
فکر کنم بری اونجا بهتر نتیچه بگیری.
http://barnamenevis.org/forum/showthread.php?t=50220
فکر کنم این کمکت کنه.

حمیدرضاصادقیان
دوشنبه 21 آبان 1386, 21:13 عصر
دوست عزیز من همین رو در برنامه خودم دارم.وقایعی که مهمه اینه که مشخص باشه در چه قسمتهایی و روی چه ردیفهایی و مثلا در چه سندهایی تغییرات ایجاد شده است.همچنین کاربر با چه نام و پسوردی و با چه کامپیوتری وارد شده است.حتی تعداد ورودهای ناموفق و اینکه با چه رمزهایی سعی کرده وارد بشه و نشده را بنویسید.در قسمت گزارشات هرگزارشی که نگاه کرد هم جای گزارش و هم کد حساب را حتما با تاریخ و ساعت قید کنید.ساعت خیلی اهمیت داره.
باید توجه تون این باشه طرف هرکاری کرد در برنامه باید ثبت بشه.حتی تهیه backup و بازیابی کردن اطلاعات.به خاطر همین چیزها کلی برنامه ما محبوبیت داشته و کلی مورد باهمین چیز مشتریان ما گرفتن.
موفق باشید

dkhatibi
دوشنبه 21 آبان 1386, 21:24 عصر
نحوخ ی ذخیزه سازی
از یک حدول استفاده می کنید یا چن تا

حمیدرضاصادقیان
چهارشنبه 23 آبان 1386, 08:25 صبح
از یک جدول ولی یک typ تعریف کردم و تمام قسمتها رو با اون از هم جدا میکنم.

dkhatibi
پنج شنبه 24 آبان 1386, 06:17 صبح
مثلا یک فیلد نوع تغییر دارید. یکی نام کاربر را ثبت می کنه یکی تاریخ و یکی زمان و یک نام جدول و آخری هم به عنوان توضیح تغییرات.
مثلا رکورد با شماره ی فلان حذف گردید. یا دقیق تر بیان می شن؟

حمیدرضاصادقیان
جمعه 25 آبان 1386, 22:12 عصر
یک فیلد ردیف. یک فیلد مربوط به اینکه چه عملی انجام شده.یک فیلد مربوط به تاریخ و ساعت . یک فیلد مربوط به کاربر. یک فیلد مربوط به قسمت برنامه و یک فیلد مربوط به کاری که انجام داده است.

Bahmany
شنبه 26 آبان 1386, 07:19 صبح
بنده در یک پروژه دو نوع Log داشتم یکی برای ذخیره در بانک و دیگری در یک txt
اتصالها و دسترسی های غیر مجاز کاربران ( یعنی اگر کاربری سعی می کرد وارد محیطی Disable شده شود نام او ثبت می شد) در بانک اطلاعاتی ذخیره می شد و رویدادهای OnError نیز در یک فایل txt ذخیره می شدند تا کار مدیر سیستم را راحتتر کنند

SYNDROME
شنبه 26 آبان 1386, 16:23 عصر
می توانی IP کامپیوتر و یا نام کامپیوتر را ذخیره کنی.
حتی می توانی رکورد را قبل از ویرایش و بعد از ویرایش نیز ذخیره کنی.
موفق باشید

dkhatibi
دوشنبه 28 آبان 1386, 06:20 صبح
یعنی اگر کاربری سعی می کرد وارد محیطی Disable شده شود نام او ثبت می ش
این کار واقعا لازمه چون کاربر ممکنه به طور اتفاقی هم زیاد این کارو انجام بده و همچنین کدها رو پیچیده می کنه!


می توانی IP کامپیوتر و یا نام کامپیوتر را ذخیره کنی.
با ذخیره ی نام کاربر لازم به این مورد هست؟

nasr
دوشنبه 28 آبان 1386, 07:43 صبح
سلام
ایجاد یک جدول برای Log کلیه تغییرات اعمال شده در جداول :
1- اول یک جدول جدید می سازیم :



CREATE TABLE [LogTable] (
[LOG_ID] [bigint] IDENTITY (1, 1) NOT NULL ,
[LOG_Table] [varchar] (80) NOT NULL , --نام جدول
[LOG_Condition] [varchar] (2000) NULL , --شرط برای تغییر - فقط روی کلید اصلی
[LOG_ConditionD] [varchar] (2000) NULL , --شرط برای حذف
[LOG_Action] [char] (1) NOT NULL , --I(Insert), D(Delete), U(Update)
[LOG_Date] [datetime] NOT NULL DEFAULT (getdate()), --تاریخ
[LOG_User] [varchar] (50) DEFAULT (user_name()), --نام کاربر تغییر دهنده
[LOG_Application] [varchar] (100) DEFAULT (app_name() NULL) --نام برنامه کاربردی تغییر دهنده
)
GO

بعد نوشتن رویه ای که تریگرهای مورد نیاز برای جداول رو ایجاد کنه :



CREATE Procedure usp_GenerateTrigger
@TableName sysname
AS
BEGIN
DECLARE @Body_G nvarchar(1000), @Body_I nvarchar(4000)
, @Body_U nvarchar(4000), @Body_D nvarchar(4000)
DECLARE @PreCond nvarchar(200), @EquCond nVarchar(1000), @InEquCond nvarchar(1000)
DECLARE @Cond_U nvarchar(1000), @Cond_D nvarchar(1000), @Keys nvarchar(900)
DECLARE @Table sysname, @Schema sysname
DECLARE @Column sysname, @DataType Sysname, @IsIdentity bit
SELECT @Table =PARSENAME(@TableName,1)
, @Schema=ISNULL(PARSENAME(@TableName, 2), CURRENT_USER), @IsIdentity=0

SELECT @Body_G='IF EXISTS (SELECT * FROM SysObjects '+char(13)
+ ' WHERE Type = ''TR'' AND id = Object_id('''+@Schema+'.insTR_Audit_'+ @Table+''')) '+char(13)
+ ' Drop Trigger '+@Schema+'.insTR_Audit_'+@Table+char(13)
+ ' IF EXISTS (SELECT * FROM SysObjects '+char(13)
+ ' WHERE Type = ''TR'' AND id = Object_id('''+@Schema+'.updelTR_Audit_' + @Table+''')) '+char(13)
+ ' Drop Trigger '+@Schema+'.updelTR_Audit_'+@Table+char(13)
+ ' IF EXISTS (SELECT * FROM SysObjects '+char(13)
+ ' WHERE Type = ''TR'' AND id = Object_id('''+@Schema+'.delTR_Audit_' + @Table + ''')) '+char(13)
+ ' Drop Trigger '+@Schema+'.delTR_Audit_'+@Table+char(13)

Select @Body_I ='', @Body_U ='', @Body_D ='',
@EquCOnd ='', @InEquCond ='', @PreCond='',
@Cond_U='', @Cond_D ='', @Keys =''

select @Body_I ='Create Trigger insTR_Audit_'+@Table +' ON '+ @TableName +'
For Insert
As
', @Body_U='Create Trigger updelTR_Audit_'+@Table +' ON '+@TableName+ '
For Update
As
', @Body_d='Create Trigger delTR_Audit_'+@Table+' ON '+@TableName+'
For Delete
As
'

Select @Keys= @Keys +', ['+ COL_Name(Object_ID(@TableName), k.COLID)+']'
from sysIndexKeys k, sysindexes I
Where i.id=object_ID(@TableName) and
i.id = k.id and i.indid=k.indid and
i.status & 0x800 =0x800
order by keyno
--Select @keys
IF LEN(@Keys)>1
select @Keys = SUBSTRING(@Keys, 3, LEN(@Keys)-2)
ELSE
BEGIN
PRINT 'No Primary Keys are available to handle the operation'
RETURN
END

IF CharIndex(', [', @Keys, 2)=0 --there is only one field now check whether it is identity
BEGIN
IF Exists(Select * from syscolumns where name =Substring(@Keys,2, LEn(@Keys)-2) and autoval is not null)
Set @IsIdentity=1
END


Declare FieldList Cursor FOR
Select COLUMN_NAME, DATA_TYPE from Information_Schema.Columns Where TABLE_Name =@Table and TABLE_SCHEMA=@Schema and Data_Type <> 'TimeStamp'
Open FieldList
FETCH NEXT FROM FieldList INTO @Column, @DataType
WHILE @@FETCH_STATUS=0
BEGIN

IF CHARINDEX(''+@Column+'', @Keys)>0
SELECT @Cond_U =@Cond_U+ '+'' AND ' +@Column +' = ''+'+
CASE
WHEN @DataType in ('Smalldatetime', 'DateTime') THEN '
''''''''+ Convert(Varchar(30), I.'+ @Column +', 113)+''''''''
'
WHEN @DataType in ('bigint','bit','BINARY', 'varbinary', 'int', 'smallint', 'tinyint', 'real', 'decimal', 'float', 'money', 'numeric') THEN
' Convert(Varchar(35), I.'+ @Column +')
'
ELSE
' ''''''''+I.'+ @Column + '+''''''''
'
END,
@EquCond = @EquCond+ ' AND I.'+ @Column +' = D.'+@Column,
@InEquCond = @InEquCond+ ' AND I.'+ @Column +' <> D.'+@Column,
@PreCond = @preCond+' AND Update('+ @Column+')',
@Cond_d =@Cond_d+ '+'' AND ' +@Column +' = ''+'+
CASE
WHEN @DataType in ('Smalldatetime', 'DateTime') THEN '
''''''''+ Convert(Varchar(30), D.'+ @Column +', 113)+''''''''
'
WHEN @DataType in ('bigint','bit','BINARY', 'varbinary', 'int', 'smallint', 'tinyint', 'real', 'decimal', 'float', 'money', 'numeric') THEN
' Convert(Varchar(35), D.'+ @Column +')
'
ELSE
' ''''''''+D.'+ @Column + '+''''''''
'
END
FETCH NEXT FROM FieldList INTO @Column, @DataType

END
CLOSE FieldList

deallocate FieldList
IF LEN(@Cond_D)>7
SELECT @Cond_D = ''''+SUBSTRING(@Cond_D, 8, LEN(@Cond_D )-7)
IF LEN(@Cond_U)>7
SELECT @Cond_U = ''''+SUBSTRING(@Cond_U, 8, LEN(@Cond_U )-7)
IF LEN(@PreCond)>5
SELECT @PreCond= 'IF '+ SUBSTRING(@PreCond, 6, LEN(@PreCond)-5)
IF LEN(@EquCond)>5
SELECT @EquCond= ' WHERE '+ SUBSTRING(@EquCond, 6, LEN(@EquCond)-5)
IF LEN(@InEquCond)>5
SELECT @InEquCond= 'WHERE '+ SUBSTRING(@InEquCond, 6, LEN(@InEquCond)-5)


select @Body_I = @Body_I + 'IF EXISTS (Select * from Inserted)
Insert into LogTable (LOG_Table, LOG_Condition, LOG_Action)
Select '''+@Table+''', '+@Cond_U+',''I'' from Inserted I
'
IF @IsIdentity=0
SELECT @Body_U =@Body_U + 'IF EXISTS (Select * from Inserted)
'+@PreCond +'
Insert into LogTable (LOG_Table, LOG_Condition, LOG_ConditionD, LOG_Action)
Select '''+@Table+''', '+@Cond_U+','+@Cond_D+',''U'' from Inserted I, Deleted D
'+@InEquCond+'
ELSE
Insert into LogTable (LOG_Table, LOG_Condition, LOG_ConditionD, LOG_Action)
Select '''+@Table+''', '+@Cond_U+','+@Cond_D+',''U'' from Inserted I, Deleted D
'+@EquCond
Else
SELECT @Body_U =@Body_U + 'Insert into LogTable (LOG_Table, LOG_Condition, LOG_ConditionD, LOG_Action)
Select '''+@Table+''', '+@Cond_U+','+@Cond_D+',''U'' from Inserted I, Deleted D
'+@EquCond

Select @Body_D = @Body_D+'IF EXISTS (Select * from Deleted)
Insert into LogTable (LOG_Table, LOG_ConditionD, LOG_Action)
Select '''+@Table+''', '+@Cond_D+',''D'' from Deleted D
'
Execute sp_ExecuteSQL @Body_G
Execute sp_ExecuteSQL @Body_I
Execute sp_ExecuteSQL @Body_U
Execute sp_ExecuteSQL @Body_D
END
بعد رویه رو با نام یک جدول فراخوانی می کنید.


EXEC usp_GenerateTrigger 'stores'

dkhatibi
دوشنبه 28 آبان 1386, 19:34 عصر
باتشکر
نحوه ی استفاد تو دلفی چه جوریه
به علاوه بر چه اساسی داره log تهیه می کنه. یعنی با کوچکترین تغییر log تهیه می شه!

nasr
سه شنبه 29 آبان 1386, 07:34 صبح
با استفاده از Query Analyzer فقط کد ها را کپی و Paste کنید. خودش کارها را انجام میده.
فقط در قسمت آخر به جای ُStores نام جدولی که میخواهی Log گرفته شود را بنویس.

dkhatibi
چهارشنبه 30 آبان 1386, 06:05 صبح
و بعد از هر بار اجرای برنامه از جداول log گرفته می شه!
یعنی اینو چه جوریانتقال بدم که لازم نباشه هر بار کپی پیست بشه!

mortezakiaee
چهارشنبه 30 آبان 1386, 12:20 عصر
اگه بخواین تو یه فایل txt ثبت بشه چه طور؟
برنامه باید شرط خاصی داشته باشه؟

nasr
چهارشنبه 30 آبان 1386, 13:35 عصر
م
و بعد از هر بار اجرای برنامه از جداول log گرفته می شه!

نخیر با هربار تغییر اطلاعات جداول نام جدول و کاربر و شماره فیلد پرایمری شده و ... را مینویسه


یعنی اینو چه جوریانتقال بدم که لازم نباشه هر بار کپی پیست بشه!
شما نیاز نیست هر بار کپی پیست کنید
فقط یه بار این کار را بکنید خودش همیشه در LogTable که با قسمت اول کد ساخته میشه Log مخصوص به جدولی که در کد قسمت آخر نوشته اید انجام میشه.
شما کارهایی که گفته شد را انجام بدید مطمئن باشید جواب میده
شما امتحان کنید!

nasr
چهارشنبه 30 آبان 1386, 13:45 عصر
اگه بخواین تو یه فایل txt ثبت بشه چه طور؟
برنامه باید شرط خاصی داشته باشه؟
برای اینکار فکر کنم اگه یه تایمر بگذارید توی برنامه و هر ثانیه LogTable را اطلاعاتش را وارد فایل text کنه خوب باشه

dkhatibi
پنج شنبه 01 آذر 1386, 06:51 صبح
با فرض درست بودن تمام مطالب مشکلی برای ذخیره در فایل متنی نحواهید داشت. هر بار که لاز است با یم دستور اطلاعات را به فایل انتقال دهید.

dkhatibi
پنج شنبه 01 آذر 1386, 19:04 عصر
تشکر
عالی بود.
فقط چند تا مشکل. اگر خواسته باشیم رکورد حذف شده یا ویرایش شده را ثبت کنیم چی کار کنیم؟
مهمتر از همه یوزرها توسط برنامه ساحته می شنو چی کار کنیم که نام اون یوزرها ثبت بشن.
اسنجا همه را dbo ثبت می کنه!

dkhatibi
شنبه 03 آذر 1386, 05:56 صبح
نمی خوام پستهای تکراری در یک تاپیک داشته باشم. اما چاره ای نیست.
حداقل راهی برای پاس دادن نام کاربری که به برنامه وارد شده است را در صورتی که با این تریگر نوشته شده امکان پذیر است ذکر کنید.

nasr
شنبه 03 آذر 1386, 08:54 صبح
اگر خواسته باشیم رکورد حذف شده یا ویرایش شده را ثبت کنیم چی کار کنیم؟
در قسمت LggActin عنوان را نگاه کنید
برای هر تغییری یک حرف مشخص میگذاره
Insert = I
Edit = U
Delete = D

dkhatibi
شنبه 03 آذر 1386, 19:13 عصر
نه منظورم نوع عمل نبود. ثبت خود رکورد ویرایش شده یا حذف شده.
از این بگذریم. مشکل یوز را چه جوری حل کنیم خیلی مهمتر از همه چیه. اگر یوزر درست ثبت نشه این نوع Log گرفتن عملا بی فایده خواهد بود.

dkhatibi
سه شنبه 06 آذر 1386, 06:19 صبح
من فعلا تنها کاری که تونسنم انجام بدم. نوشتن رویدادهای BeforeEdit,post,insert,delete بود تا به کمک اون Log را ایجاد کنم. از یک جدول استفاده کردم و لذا از یکد مشترک برای تمام جداول استفاده شد. در موقع delete یا Edit هم در فیلدی به نام Coment نام فیلدها به همراه مقدار اولیه ی هر فیلد را ثبت کردم. مشکلی که داره اینه که نام فیلدها برای کاربر معمولی قابل فهم نمی باشد. به هر حال بهتر از هیچ چی بود.
بعضی از تغییرات دیگر مانند ورود و خرووج و کلمات رمز نادرست نیز در این جدول ثبت می شن.

تا راه حل بهتری بیابیم.....

nasr
سه شنبه 06 آذر 1386, 07:37 صبح
من فعلا تنها کاری که تونسنم انجام بدم. نوشتن رویدادهای BeforeEdit,post,insert,delete بود تا به کمک اون Log را ایجاد کنم. از یک جدول استفاده کردم و لذا از یکد مشترک برای تمام جداول استفاده شد. در موقع delete یا Edit هم در فیلدی به نام Coment نام فیلدها به همراه مقدار اولیه ی هر فیلد را ثبت کردم. مشکلی که داره اینه که نام فیلدها برای کاربر معمولی قابل فهم نمی باشد. به هر حال بهتر از هیچ چی بود.
بعضی از تغییرات دیگر مانند ورود و خرووج و کلمات رمز نادرست نیز در این جدول ثبت می شن.

تا راه حل بهتری بیابیم.....
خوبه
من هم دارم روی اون کار می کنم انشالله بشه تکمیلش کرد

dkhatibi
سه شنبه 06 آذر 1386, 18:24 عصر
اگر کمی حوصله به خرج دهیم می شه جدولی اضافه کرد که حاوی یک فیلد نام جدول و یک فیلد نام فیلد اون جدول و فیلد دیگه نامی که برای کاربر باید نمایش داده شود باشدو به این ترتیب فیلد Coment گفته شده را اصلاح کرد.