[Tutorial] Logging things that happen on your server
#1

Tutorial - Logging things that happen on your server


Description:

As people are making more and more servers, and more and more people are using SA:MP, server owners would want to keep track of what's going on on their servers. Therefore, I decided to make a topic showing you guys how to log things that happen on your server. It's very simple once you get the hang of it. I'll explain everything as we go along. This is my first tutorial and my first time explaining pawn to someone else. If I went wrong somewhere, please, tell me.

Tutorial:

First of all, add these to the top of your script, somewhere before main().

pawn Code:
new receivername[MAX_PLAYER_NAME];
new sendername[MAX_PLAYER_NAME];
new giveplayerid[MAX_PLAYERS];
These are a bit like strings, because they are arrayed. The [MAX_PLAYER_NAME] arrarys how many characters you can have in a nickname. [MAX_PLAYERS] is the max player slots you have on your server.

The next thing you'd want to do is create a forward and public declaration for the logs you want to make. I'd highly recommend that you don't log every single command onto a different file, as there would be too many files and it'll be a lot harder work. I'll make a KickLog for this tutorial. For that, we need to forward the callback.

pawn Code:
forward KickLog(string[])
The "string[]" means that there is some sort of text inside those square brackets, as you do with arrays. The next thing you'd need to do is create the public declaration for this, else if you come to compile it, it will come up with an error saying "error 004: function "KickLog" is not implemented".

So, anywhere under main(), you can add the following, and it's good because you can even add it at the bottom of your script so you know where it is at all times.

pawn Code:
public KickLog(string[])
{
    new entry[250];
    format(entry, sizeof(entry), "%s",string);
    new File:hFile;
    hFile = fopen("/Logs/kick.log", io_append);
    fwrite(hFile, entry);
    fclose(hFile);
}
Below, I have made some explanations on what this all does.

pawn Code:
new entry[250];
This code is saying that the word entry as having an array of 250 max characters, don't worry, you'll never get up to that anyway.

pawn Code:
format(entry, sizeof(entry), "%s",string);
This %s is a string, which if you dumb it down means characters, words, sentences or however you like it. This is also telling the script that entry is the string, and the sizeof the entry is 250 as was defined above.

pawn Code:
new File:hFile;
This is basically telling the script that we are using a File: format, just as you do with Float: (but a lot different).

pawn Code:
hFile = fopen("/Logs/kick.log", io_append);
This code is telling the script what file to open, if you use the same as what I've done, it will create a document in scriptfiles/Logs. To make that work, you will need to create a folder in scriptfiles called Logs, as this code doesn't tell the script to create a folder if it doesn't exist. This code is also telling the script that if the kick.log file doesn't exist, that it can create one, that's what "fopen" does, along side with opening the file of course.

pawn Code:
fwrite(hFile, entry);
This code is writing the entry inside that kick.log file. Remember what we did to "entry" above in the second line.

pawn Code:
fclose(hFile);
This is now closing that file, as we don't need it anymore.

Now, the next step is to create what the log will log will look like once something happens. Let's do that now. So, if you are making a kick log, then obviously you'd want to go to the command /kick. So go there and then somewhere near the bottom you can add the following:

pawn Code:
new year, month, day; getdate(year, month, day); new hour, minute, second; gettime(hour, minute, second);
This code will basically get the date and the time, so we know when exactly the occurrence took place at.

pawn Code:
new senderip[64]; GetPlayerIp(playerid, senderip, sizeof(senderip));
This code is getting the IP address of the player who sent the command. This can come handy when you are working with hacked accounts, e.g. someone is spamming /kick and you want to know if it's actually him or not, then you can take a look at the IP and if it's not the same then you know that their account was hacked.

pawn Code:
new receiverip[64]; GetPlayerIp(giveplayerid, receiverip, sizeof(receiverip));
This is pretty much the same, it will get the IP of the receiver. Or the person who got kicked in other words.

pawn Code:
format(string, sizeof(string), "%d/%d/%d %d:%d:%d Sendername: %s SenderIP: %s Receivername: %s ReceiverIP: %s Reason: %s \r\n", day, month, year, hour, minute, second, sendername, senderip, receivername, receiverip, reason);
This is the string that we will be using. PS: If you don't have a string array towards the top of your /kick command, then add new string[211]; or any number. The "%d/%d/%d" logs the date of the incident, the %d:%d:%d will log the time. You can switch those around by taking a look at how the %d is being used towards the end of the line. Sendername will show the sender name, of course, and then the SenderIP shows the IP of the person who sent the command. Same with the Receivername and the ReceiverIP, who is the one that got the command performed on. And then the Reason will come up with what reason you gave that kick for. And finally, the \r and \n will make a new line after the previous /kick.

What it will all look like overall:

Your code would look eventually something like the code below. PS: I am using y_commands, it's pretty much the same process with any command processor, including the default one.

pawn Code:
new receivername[MAX_PLAYER_NAME];
new sendername[MAX_PLAYER_NAME];
new giveplayerid[MAX_PLAYERS];

forward KickLog(string[]);

public KickLog(string[])
{
    new entry[256];
    format(entry, sizeof(entry), "%s",string);
    new File:hFile;
    hFile = fopen("/Logs/kick.log", io_append);
    fwrite(hFile, entry);
    fclose(hFile);
}

YCMD:kick(playerid, params[], help)
{
    if(help)
    {
        SendClientMessage(playerid, COLOR_WHITE, "{AFAFAF}Command /kick: {FFFFFF}Admins can use this command to kick other players.");
    }
    else
    {
        if(PlayerInfo[playerid][pAdmin] >= 1)
        {
            new string[158], reason[120], giveplayerid;
            if(sscanf(params, "us[120]", giveplayerid, reason)) return SendClientMessage(playerid, COLOR_WHITE, "{AFAFAF}Syntax: {FFFFFF}/kick [playerid/name] [reason]");
            if(giveplayerid == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_WHITE, "{AFAFAF}Error: {FFFFFF}Player not connected.");
            GetPlayerName(playerid, sendername, sizeof(sendername)); GetPlayerName(giveplayerid, receivername, sizeof(receivername));
            format(string, sizeof(string), "{FF6347}Admin %s kicked %s, reason: %s", sendername, receivername, reason);
            SendClientMessageToAll(COLOR_WHITE, string); SetTimerEx("giveplayeridKick", 1000, false, "i", giveplayerid);
            new year, month, day; getdate(year, month, day); new hour, minute, second; gettime(hour, minute, second);
            new senderip[64]; GetPlayerIp(playerid, senderip, sizeof(senderip));
            new receiverip[64]; GetPlayerIp(giveplayerid, receiverip, sizeof(receiverip));
            format(string, sizeof(string), "%d/%d/%d %d:%d:%d Sendername: %s SenderIP: %s Receivername: %s ReceiverIP: %s Reason: %s \r\n", day, month, year, hour, minute, second, sendername, senderip, receivername, receiverip, reason); KickLog(string);
        } else { SendClientMessage(playerid, COLOR_WHITE, ""MinimumAdmin1""); return 1; }
    }
    return 1;
}
What the log will look like:

That's it, you've made a kick log. Make sure you have a folder called Logs in your scriptfiles, or it will not work. This is what the log would look like after you've completed it:

Code:
24/8/2013 18:57:25 Sendername: DanishHaq SenderIP: 192.168.0.8 Receivername: testaccount ReceiverIP: 192.168.0.8 Reason: this is the reason
Wait!

I recommend opening the file with gVim (http://www.vim.org/download.php) as it will show the lines between the kick entries and makes it easier for you to read and understand.
Reply
#2

It's nice, but you're limiting it just to the kick command. I know you can do it for the things you want but here's a similar way to do it:
pawn Code:
Log(FileName[], Input[]) {

    new string[156], date[2][3], File: fileHandle = fopen(FileName, io_append);
    gettime(date[0][0], date[0][1], date[0][2]);
    getdate(date[1][0], date[1][1], date[1][2]);
    format(string, sizeof(string), "[%i/%i/%i - %i:%i:%i] %s\r\n", date[1][2], date[1][1], date[1][0], date[0][0], date[0][1], date[0][2], Input);
    fwrite(fileHandle, string);
    return fclose(fileHandle);
}
Reply
#3

Quote:
Originally Posted by Elysian`
View Post
It's nice, but you're limiting it just to the kick command. I know you can do it for the things you want but here's a similar way to do it:
pawn Code:
Log(FileName[], Input[]) {

    new string[156], date[2][3], File: fileHandle = fopen(FileName, io_append);
    gettime(date[0][0], date[0][1], date[0][2]);
    getdate(date[1][0], date[1][1], date[1][2]);
    format(string, sizeof(string), "[%i/%i/%i - %i:%i:%i] %s\r\n", date[1][2], date[1][1], date[1][0], date[0][0], date[0][1], date[0][2], Input);
    fwrite(fileHandle, string);
    return fclose(fileHandle);
}
True, I knew there were other ways to do it, but I couldn't figure it out . Thanks for your help, I'll take it on board, as some kind of guidance.

Also, for the person who minus rep'd me for this reason:

Quote:

u got this code from a script, since u put if(PlayerInfo[playerid][pAdmin] >= 1), thats why im -rep, also why ycmd without including it or smthn?

I didn't get the code from another script, I've been scripting it myself for the past 3-4 days. Just because my variable is pAdmin means I am using an existing script? Funny joke. I'd show you my script by any means, unfinished, nothing near to finished. And that final code, it was just an example of what it would / could look like, it wasn't exact of course, derp. Nearly everyone's /kick command will be different, mines like this, big deal?
Reply
#4

Thanks for the awesome tutorial, now I can keep eyes on what happends everywhere. +Rep
Reply
#5

Quote:
Originally Posted by CrazyChoco
View Post
Thanks for the awesome tutorial, now I can keep eyes on what happends everywhere. +Rep
No problem, glad you're happy . Thanks for the rep.

Quote:

This forum requires that you wait 120 seconds between posts. Please try again in 103 seconds.

That forum speed .
Reply
#6

Awesome tutorial, this truley can keep server owners able to know what is happening everywhere, awesome.
Reply
#7

A good one, yet I need to point something out: Chatlogging from 0.3X has made logging pretty useless. Also, if you use ZCMD - a simple print statement under OnPlayerCommandPerformed would do everything.
Reply
#8

Quote:
Originally Posted by BigBadWolf
View Post
Awesome tutorial, this truley can keep server owners able to know what is happening everywhere, awesome.
Thanks . Glad you liked it.

Quote:
Originally Posted by Rajat_Pawar
View Post
A good one, yet I need to point something out: Chatlogging from 0.3X has made logging pretty useless. Also, if you use ZCMD - a simple print statement under OnPlayerCommandPerformed would do everything.
Yea.. When I get home from work today I'll change it to the regular pawno command processor actually, it's be easier for the newbies to understand. Thanks for the advice .
Reply
#9

Good tutorial. ...

Really helpful.
Reply
#10

Quote:
Originally Posted by iAnonymous
View Post
Good tutorial. ...

Really helpful.
Thanks, glad you found it helpful .
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)