├── src ├── docs │ ├── ConvertFrom-EZlog.md │ ├── Write-EZLog.md │ └── Invoke-EZLogRotation.md ├── EZLog.psd1 ├── EZLog.psm1 ├── EZLog.Tests.ps1 └── en-US │ └── EZLog-help.xml └── README.md /src/docs/ConvertFrom-EZlog.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: EZLog-help.xml 3 | Module Name: EZLog 4 | online version: 5 | schema: 2.0.0 6 | --- 7 | 8 | # ConvertFrom-EZlog 9 | 10 | ## SYNOPSIS 11 | Cmdlet that convert an EZLog file to a set of objects. 12 | 13 | ## SYNTAX 14 | 15 | ``` 16 | ConvertFrom-EZlog [-FilePath] [] 17 | ``` 18 | 19 | ## DESCRIPTION 20 | This cmdlet allows from a log file generated by EZLog to get an object. 21 | The goal is to be able to easily filter on events with a single Where-Object and 22 | get to the info stored in the header and in the footer. 23 | 24 | Furthermore it eases the ability to transform the data to JSON if piped to ConvertTo-JSON. 25 | 26 | ## EXAMPLES 27 | 28 | ### EXAMPLE 1 29 | ``` 30 | ConvertFrom-EZlog -FilePath C:\temp\mylog.log 31 | ``` 32 | 33 | Returns an object from the log file. 34 | 35 | ### EXAMPLE 2 36 | ``` 37 | ConvertFrom-EZlog -FilePath C:\temp\mylog.log | ConvertTo-JSON 38 | ``` 39 | 40 | Get a JSON format from a logfile. 41 | 42 | ## PARAMETERS 43 | 44 | ### -FilePath 45 | Specify the log file's path. 46 | 47 | ```yaml 48 | Type: String 49 | Parameter Sets: (All) 50 | Aliases: Path 51 | 52 | Required: True 53 | Position: 1 54 | Default value: None 55 | Accept pipeline input: True (ByValue) 56 | Accept wildcard characters: False 57 | ``` 58 | 59 | ### CommonParameters 60 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 61 | 62 | ## INPUTS 63 | 64 | ## OUTPUTS 65 | 66 | ## NOTES 67 | AUTHOR: Arnaud PETITJEAN - arnaud@powershell-scripting.com 68 | LASTEDIT: 2016/11/15 69 | 70 | ## RELATED LINKS 71 | -------------------------------------------------------------------------------- /src/EZLog.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'EZLog' 3 | # 4 | # Generated by: Arnaud PETITJEAN 5 | # 6 | # Generated on: 12/08/2022 7 | # 8 | 9 | @{ 10 | 11 | # Script module or binary module file associated with this manifest. 12 | RootModule = 'EZLog.psm1' 13 | 14 | # Version number of this module. 15 | ModuleVersion = '2.2.12' 16 | 17 | # ID used to uniquely identify this module 18 | GUID = '9f9d9559-2f69-4e46-83c8-c7ab739e745b' 19 | 20 | # Author of this module 21 | Author = 'Arnaud PETITJEAN' 22 | 23 | # Company or vendor of this module 24 | CompanyName = 'Start-Scripting.io' 25 | 26 | # Copyright statement for this module 27 | Copyright = '(c) 2025 Arnaud PETITJEAN. All rights reserved.' 28 | 29 | # Description of the functionality provided by this module 30 | Description = 'A very easy and pragmatic log module for admins in a hurry. See project site on Github for more info.' 31 | 32 | # Minimum version of the Windows PowerShell engine required by this module 33 | PowerShellVersion = '5.1' 34 | 35 | # Name of the Windows PowerShell host required by this module 36 | # PowerShellHostName = '' 37 | 38 | # Minimum version of the Windows PowerShell host required by this module 39 | # PowerShellHostVersion = '' 40 | 41 | # Minimum version of Microsoft .NET Framework required by this module 42 | #DotNetFrameworkVersion = '2.0' 43 | 44 | # Minimum version of the common language runtime (CLR) required by this module 45 | # CLRVersion = '' 46 | 47 | # Processor architecture (None, X86, Amd64) required by this module 48 | # ProcessorArchitecture = '' 49 | 50 | # Modules that must be imported into the global environment prior to importing this module 51 | # RequiredModules = @() 52 | 53 | # Assemblies that must be loaded prior to importing this module 54 | # RequiredAssemblies = @() 55 | 56 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 57 | # ScriptsToProcess = @() 58 | 59 | # Type files (.ps1xml) to be loaded when importing this module 60 | # TypesToProcess = @() 61 | 62 | # Format files (.ps1xml) to be loaded when importing this module 63 | # FormatsToProcess = @() 64 | 65 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 66 | # NestedModules = @() 67 | 68 | # Functions to export from this module 69 | FunctionsToExport = @('Write-EZLog','ConvertFrom-EZLog','Invoke-EZLogRotation') 70 | #FunctionsToExport = '*' 71 | 72 | # Cmdlets to export from this module 73 | CmdletsToExport = '' 74 | 75 | # Variables to export from this module 76 | VariablesToExport = '' 77 | 78 | # Aliases to export from this module 79 | AliasesToExport = '' 80 | 81 | # DSC resources to export from this module 82 | # DscResourcesToExport = @() 83 | 84 | # List of all modules packaged with this module 85 | # ModuleList = @() 86 | 87 | # List of all files packaged with this module 88 | # FileList = @() 89 | 90 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 91 | PrivateData = @{ 92 | 93 | PSData = @{ 94 | 95 | # Tags applied to this module. These help with module discovery in online galleries. 96 | Tags = 'write-log', 'log', 'logging', 'easy', 'simple', 'rotation', 'rotate', 'logrotate' 97 | 98 | # A URL to the license for this module. 99 | # LicenseUri = '' 100 | 101 | # A URL to the main website for this project. 102 | ProjectUri = 'http://github.com/apetitjean/ezlog' 103 | 104 | # A URL to an icon representing this module. 105 | # IconUri = '' 106 | 107 | # ReleaseNotes of this module 108 | # ReleaseNotes = 'Minor bug fix.' 109 | 110 | } # End of PSData hashtable 111 | 112 | } # End of PrivateData hashtable 113 | 114 | # HelpInfo URI of this module 115 | # HelpInfoURI = '' 116 | 117 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 118 | # DefaultCommandPrefix = '' 119 | } 120 | -------------------------------------------------------------------------------- /src/docs/Write-EZLog.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: EZLog-help.xml 3 | Module Name: EZLog 4 | online version: 5 | schema: 2.0.0 6 | --- 7 | 8 | # Write-EZLog 9 | 10 | ## SYNOPSIS 11 | Utility cmdlet to write logs to disk in an easy and pragmatic way. 12 | 13 | ## SYNTAX 14 | 15 | ### set2 (Default) 16 | ``` 17 | Write-EZLog [-Category] [-Message] -LogFile [-Delimiter ] [-ToScreen] 18 | [] 19 | ``` 20 | 21 | ### set1 22 | ``` 23 | Write-EZLog [-Header] -LogFile [-Delimiter ] [-ToScreen] [] 24 | ``` 25 | 26 | ### set3 27 | ``` 28 | Write-EZLog [-Footer] -LogFile [-Delimiter ] [-ToScreen] [] 29 | ``` 30 | 31 | ## DESCRIPTION 32 | This cmdlet allows to write timestamped and nice formatted logs with a header and footer. 33 | It also allows to specify if the log entry being written is an info, a warning or an error. 34 | 35 | The header contains the following information : 36 | - full script path of the caller, 37 | - account under the script was run, 38 | - computer name of the machine whose executed the script, 39 | - and more... 40 | 41 | The footer contains the elapsed time from the beginning of the log session. 42 | 43 | ## EXAMPLES 44 | 45 | ### EXAMPLE 1 46 | 47 | ```PowerShell 48 | # First thing to do is write a header and define a log file where the data will be written to. 49 | 50 | Write-EZLog -Header -LogFile C:\logs\mylogfile.log 51 | ``` 52 | 53 | ### EXAMPLE 2 54 | 55 | ```PowerShell 56 | # Next, anywhere in your script when you need to write a log, do one of the folowing command: 57 | 58 | Write-EZLog -Category INF -Message 'This is an info to be written in the log file' 59 | Write-EZLog -Category WAR -Message 'This is a warning to be written in the log file' 60 | Write-EZLog -Category ERR -Message 'This is an error to be written in the log file' 61 | ``` 62 | 63 | ### EXAMPLE 3 64 | 65 | ```PowerShell 66 | # Finaly, to close your logfile you need to write a footer, just do that: 67 | 68 | Write-EZLog -Footer 69 | ``` 70 | 71 | ### EXAMPLE 4 72 | 73 | ```PowerShell 74 | # If you want to see the logs in the PowerShell console whereas they are still written to disk, you can specify the -ToScreen switch. 75 | # Info entries will be written in cyan color, Yellow for warnings, and Red for the errors. 76 | 77 | Write-EZLog -Category WAR -Message 'This is a warning to be written in the log file' -ToScreen 78 | ``` 79 | 80 | ## PARAMETERS 81 | 82 | ### -Category 83 | Category can be one of the following value : INF, WAR, ERR 84 | 85 | ```yaml 86 | Type: MsgCategory 87 | Parameter Sets: set2 88 | Aliases: 89 | Accepted values: INF, WAR, ERR 90 | 91 | Required: True 92 | Position: 1 93 | Default value: None 94 | Accept pipeline input: False 95 | Accept wildcard characters: False 96 | ``` 97 | 98 | ### -Message 99 | Specify the content of the data to log. 100 | 101 | ```yaml 102 | Type: String 103 | Parameter Sets: set2 104 | Aliases: Msg 105 | 106 | Required: True 107 | Position: 2 108 | Default value: None 109 | Accept pipeline input: False 110 | Accept wildcard characters: False 111 | ``` 112 | 113 | ### -Header 114 | Mandatory switch to start a log session. 115 | 116 | ```yaml 117 | Type: SwitchParameter 118 | Parameter Sets: set1 119 | Aliases: 120 | 121 | Required: True 122 | Position: Named 123 | Default value: False 124 | Accept pipeline input: False 125 | Accept wildcard characters: False 126 | ``` 127 | 128 | ### -Footer 129 | Mandatory switch to end a log session. 130 | If you omit to close your log session, you won't know how much time 131 | your script was running. 132 | 133 | ```yaml 134 | Type: SwitchParameter 135 | Parameter Sets: set3 136 | Aliases: 137 | 138 | Required: True 139 | Position: Named 140 | Default value: False 141 | Accept pipeline input: False 142 | Accept wildcard characters: False 143 | ``` 144 | 145 | ### -LogFile 146 | Path to the log file to be created. 147 | 148 | ```yaml 149 | Type: String 150 | Parameter Sets: (All) 151 | Aliases: 152 | 153 | Required: True 154 | Position: Named 155 | Default value: None 156 | Accept pipeline input: False 157 | Accept wildcard characters: False 158 | ``` 159 | 160 | ### -Delimiter 161 | Specify a delimiter to be used in order to separate the fields in a log entry. 162 | 163 | ```yaml 164 | Type: Char 165 | Parameter Sets: (All) 166 | Aliases: 167 | 168 | Required: False 169 | Position: Named 170 | Default value: $( if ((Get-Culture).TextInfo.ListSeparator -eq ' ') {','} else {(Get-Culture).TextInfo.ListSeparator}) 171 | Accept pipeline input: False 172 | Accept wildcard characters: False 173 | ``` 174 | 175 | ### -ToScreen 176 | Displays the logs in the log file and in the console. 177 | 178 | ```yaml 179 | Type: SwitchParameter 180 | Parameter Sets: (All) 181 | Aliases: 182 | 183 | Required: False 184 | Position: Named 185 | Default value: False 186 | Accept pipeline input: False 187 | Accept wildcard characters: False 188 | ``` 189 | 190 | ### CommonParameters 191 | This cmdlet supports the common parameters: Debug, ErrorAction, ErrorVariable, InformationAction, InformationVariable, OutVariable, OutBuffer, PipelineVariable, Verbose, WarningAction, and WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 192 | 193 | ## INPUTS 194 | 195 | ## OUTPUTS 196 | 197 | ## NOTES 198 | AUTHOR: Arnaud PETITJEAN - apetitjean@start-scripting.io 199 | LASTEDIT: 2023/11/30 200 | 201 | ## RELATED LINKS 202 | [See my Github repository](https://github.com/apetitjean/EZLog) -------------------------------------------------------------------------------- /src/docs/Invoke-EZLogRotation.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: EZLog-help.xml 3 | Module Name: EZLog 4 | online version: 5 | schema: 2.0.0 6 | --- 7 | 8 | # Invoke-EZLogRotation 9 | 10 | ## SYNOPSIS 11 | Clean up old log files in order to keep only the most recent ones. 12 | 13 | ## SYNTAX 14 | 15 | ### set1 16 | ``` 17 | Invoke-EZLogRotation [-Path] [-Filter] -Newest [-ArchiveTo ] 18 | [-OverwriteArchive] [] 19 | ``` 20 | 21 | ### set2 22 | ``` 23 | Invoke-EZLogRotation [-Path] [-Filter] [-Interval] [-ArchiveTo ] 24 | [-OverwriteArchive] [] 25 | ``` 26 | 27 | ## DESCRIPTION 28 | Ancient logs files are either deleted or archived into a Zip file. 29 | 30 | Options are available to specify how many newest files to keep. 31 | It's also possible to determine a time interval for the logs to keep (daily, monthly, yearly) 32 | 33 | ## EXAMPLES 34 | 35 | ### EXAMPLE 1 36 | ``` 37 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Newest 15 38 | ``` 39 | 40 | Only keeps the latest 15 newest *.log files in the C:\LogFiles directory. 41 | Older files will be deleted. 42 | 43 | ### EXAMPLE 2 44 | ``` 45 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Newest 15 -ArchiveTo C:\LogFiles\archive.zip 46 | ``` 47 | 48 | Only keeps the latest 15 newest *.log files in the C:\LogFiles directory. 49 | Before deletion, older files 50 | will be archived into the C:\LogFiles\archive.zip. 51 | If the archive.zip file already exists, logs will be appended to it. 52 | 53 | ### EXAMPLE 3 54 | ``` 55 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Newest 15 -ArchiveTo C:\LogFiles\archive.zip -OverwriteArchive 56 | ``` 57 | 58 | Only keeps the latest 15 newest *.log files in the C:\LogFiles directory. 59 | Before deletion, older files 60 | will be archived into the C:\LogFiles\archive.zip. 61 | If the archive.zip file already exists it will be overwritten. 62 | 63 | ### EXAMPLE 4 64 | ``` 65 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Interval Daily 66 | ``` 67 | 68 | Only keeps the *.log files of the day in the C:\LogFiles directory. 69 | Older files will be deleted. 70 | 71 | ### EXAMPLE 5 72 | ``` 73 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Interval Monthly 74 | ``` 75 | 76 | Only keeps the *.log files of the month in the C:\LogFiles directory. 77 | Older files will be deleted. 78 | 79 | ### EXAMPLE 6 80 | ``` 81 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Interval Monthly -ArchiveTo C:\LogFiles\archive.zip -Overwrite 82 | ``` 83 | 84 | Only keeps the *.log files of the month in the C:\LogFiles directory. 85 | Older files will be archived monthly. 86 | 87 | ### EXAMPLE 7 88 | ``` 89 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Interval Yearly 90 | ``` 91 | 92 | Only keeps the *.log files of the current year in the C:\LogFiles directory matching the pattern *.log. 93 | Older files will be deleted. 94 | 95 | ## PARAMETERS 96 | 97 | ### -Path 98 | Directory containing the logs to rotate. 99 | 100 | ```yaml 101 | Type: String 102 | Parameter Sets: (All) 103 | Aliases: 104 | 105 | Required: True 106 | Position: 1 107 | Default value: None 108 | Accept pipeline input: False 109 | Accept wildcard characters: False 110 | ``` 111 | 112 | ### -Filter 113 | Pattern to identify the logs to rotate. 114 | Ex : *.log, *ezlog*.txt, etc. 115 | 116 | ```yaml 117 | Type: String 118 | Parameter Sets: (All) 119 | Aliases: 120 | 121 | Required: True 122 | Position: 2 123 | Default value: None 124 | Accept pipeline input: False 125 | Accept wildcard characters: False 126 | ``` 127 | 128 | ### -Newest 129 | Specify how many files to keep in the directory. 130 | The files are sorted by the LastWriteTime attribute 131 | and only the newest files determined by this parameter are kept. 132 | Other files are deleted or archived. 133 | 134 | ```yaml 135 | Type: Int32 136 | Parameter Sets: set1 137 | Aliases: 138 | 139 | Required: True 140 | Position: Named 141 | Default value: 0 142 | Accept pipeline input: False 143 | Accept wildcard characters: False 144 | ``` 145 | 146 | ### -Interval 147 | Specify the periodicy of the rotation. 148 | Possible values are : Daily, Monthly, Yearly 149 | 150 | Daily : Keep only the logs of the day 151 | Monthly : Keep only the logs of the month 152 | Yearly : Keep only the logs of the year 153 | 154 | ```yaml 155 | Type: Interval 156 | Parameter Sets: set2 157 | Aliases: 158 | Accepted values: Daily, Monthly, Yearly 159 | 160 | Required: True 161 | Position: 2 162 | Default value: None 163 | Accept pipeline input: False 164 | Accept wildcard characters: False 165 | ``` 166 | 167 | ### -ArchiveTo 168 | Indicate if the old logs need to be archived in a Zip before before deletion. 169 | 170 | If not specified, old logs are deleted. 171 | 172 | If specified, you must indicate a file path containing the .zip extension. 173 | Eg. 174 | : C:\logs\archive.zip 175 | 176 | If the archive file already exists, logs will be append to it. 177 | If you want to overwrite it you can use 178 | the -OverwriteArchive switch. 179 | 180 | ```yaml 181 | Type: String 182 | Parameter Sets: (All) 183 | Aliases: 184 | 185 | Required: False 186 | Position: Named 187 | Default value: None 188 | Accept pipeline input: False 189 | Accept wildcard characters: False 190 | ``` 191 | 192 | ### -OverwriteArchive 193 | Works in association with -ArchiveTo. 194 | If specified, it overwrites an archive if it already exists. 195 | 196 | ```yaml 197 | Type: SwitchParameter 198 | Parameter Sets: (All) 199 | Aliases: 200 | 201 | Required: False 202 | Position: Named 203 | Default value: False 204 | Accept pipeline input: False 205 | Accept wildcard characters: False 206 | ``` 207 | 208 | ### CommonParameters 209 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). 210 | 211 | ## INPUTS 212 | 213 | ## OUTPUTS 214 | 215 | ## NOTES 216 | AUTHOR: Arnaud PETITJEAN 217 | LASTEDIT: 2018/04/03 218 | 219 | ## RELATED LINKS 220 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build status](https://ci.appveyor.com/api/projects/status/uk66ctiqlf8ntpb2?svg=true)](https://ci.appveyor.com/project/apetitjean/ezlog) 2 | 3 | # EZLog 4 | ## A very easy and pragmatic PowerShell log module for admins in a hurry... 5 | 6 | The EZLog module is a **lightweight** set of functions aimed at providing **nice looking and professional log files**. 7 | But wait! There's no need to recall multiple commands, everything is done with only one command : `Write-EZLog`. 8 | So anywhere in a script you need to write a log on disk or/and to display an information on your screen, all you need to do is just to call `Write-EZLog` along with your message. 9 | 10 | That being said, you also have access to the following utility commands: 11 | - `ConvertFrom-EZLog` : convert a log file into an object. This could be very useful to parse logs in a directory or to convert a raw log file into a JSON file. 12 | - `Invoke-EZLogRotation` : provide log rotation. You can trim the logs based on a number of files to keep or on a regular basis (daily, weekly, monthly or yearly). 13 | 14 | **Note:** `Invoke-EZLogRotation` can be used with any log files; it is not limited to rotating logs created by this module. 15 | 16 | EZLog allows to write timestamped and nice formatted logs with a header and footer. 17 | It also allows to specify if the log entry being written is an info, a warning or an error. 18 | 19 | The header contains the following information: 20 | - full script path of the caller, 21 | - account under the script was run, 22 | - computer name of the machine whose executed the script, 23 | - and more... 24 | The footer contains the elapsed time from the beginning of the log session. 25 | 26 | Let show you a quick example of a result log file: 27 | 28 | ```Text 29 | +----------------------------------------------------------------------------------------+ 30 | Script fullname : C:\Users\Arnaud\Documents\GitRepo\Temp\script_example.ps1 31 | When generated : 2018-03-14 23:23:16 32 | Current user : DESKTOP-31O7OD0\Arnaud 33 | Current computer : DESKTOP-31O7OD0 34 | Operating System : Microsoft Windows 10 Entreprise 2016 LTSB 35 | OS Architecture : 64 bits 36 | +----------------------------------------------------------------------------------------+ 37 | 38 | 2016-09-14 23:23:19; INF; This is a regular information message. Will be displayed in Cyan color in the console. 39 | 2016-09-14 23:23:20; WAR; This is a warning message. Will be displayed in Yellow color in the console. 40 | 2016-09-14 23:23:23; ERR; This is an error message. Will be displayed in red color in the console. 41 | 42 | +----------------------------------------------------------------------------------------+ 43 | End time : 2018-03-14 23:23:25 44 | Total duration (seconds) : 9 45 | Total duration (minutes) : 0.15 46 | +----------------------------------------------------------------------------------------+ 47 | ``` 48 | 49 | Along with writing logs to a text file, you can also - if you want to - display the logs in the console. 50 | Each category of log event (Info, Warning, Error) has it's own color, so it's easy to distinguish errors or warnings among regular info messages. 51 | 52 | This is how it can look like in the console if you add the -ToScreen switch: 53 | ![ezlog_screenshot_01](https://cloud.githubusercontent.com/assets/10902523/23906931/d280dae8-08cf-11e7-868b-c0f737633e2a.png) 54 | 55 | EZLog does not provide all the bells and whistles NxLog can offer, but instead **EZLog** is **very efficient** and super **mega easy to use**. 56 | 57 | --- 58 | ## How to use EZLog? 59 | 60 | ### EXAMPLE 1 61 | First thing to do is write a header and define a log file where the data will be written to. You have to specify the log file parameter on every command unless you use the `$PSDefaultParameterValues` variable as shown in example 2. 62 | 63 | ```PowerShell 64 | Write-EZLog -Header -LogFile C:\logs\mylogfile.log 65 | ``` 66 | Next, anywhere in your script when you need to write a log, do one of the folowing command: 67 | 68 | ```PowerShell 69 | Write-EZLog -Category INF -Message 'This is an info to be written in the log file' -LogFile C:\logs\mylogfile.log 70 | Write-EZLog -Category WAR -Message 'This is a warning to be written in the log file' -LogFile C:\logs\mylogfile.log 71 | Write-EZLog -Category ERR -Message 'This is an error to be written in the log file' -LogFile C:\logs\mylogfile.log 72 | ``` 73 | 74 | Finaly, to close your logfile you need to write a footer, just do that: 75 | 76 | ```PowerShell 77 | Write-EZLog -Footer -LogFile C:\logs\mylogfile.log 78 | ``` 79 | 80 | This way you will get a nice footer on your log file and you also get the total duration of your script, which could be a valuable information in many cases! 81 | 82 | ### EXAMPLE 2 83 | To avoid specifying the parameters everytime you call `Write-EZLog`, you can use the `$PSDefaultParametersValue` variable of PowerShell. 84 | 85 | In addition, EZLog allows you to specify any delimiter character. So we can define it only once at the beginning of a script, like below: 86 | 87 | ```PowerShell 88 | $LogFile = 'C:\logs\mylogfile.log' 89 | $PSDefaultParameterValues = @{ 'Write-EZLog:LogFile' = $LogFile ; 90 | 'Write-EZLog:Delimiter' = ';' 91 | } 92 | 93 | Write-EZLog -Header 94 | Write-EZLog -Category INF -Message 'This is an info to be written in the log file' 95 | Write-EZLog -Category WAR -Message 'This is a warning to be written in the log file' 96 | Write-EZLog -Category ERR -Message 'This is an error to be written in the log file' 97 | Write-EZLog -Footer 98 | ``` 99 | 100 | ### EXAMPLE 3 101 | If you want to see the logs in the PowerShell console whereas they are still written to disk, 102 | you can specify the `-ToScreen` switch. 103 | Info entries will be written in cyan color, Yellow for warnings, and Red for the errors. 104 | 105 | ```PowerShell 106 | $PSDefaultParameterValues = @{ 'Write-EZLog:LogFile' = $LogFile ; 107 | 'Write-EZLog:Delimiter' = ';' ; 108 | 'Write-EZLog:ToScreen' = $true } 109 | 110 | Write-EZLog -Category WAR -Message 'This is a warning to be written in the log file' 111 | ``` 112 | 113 | ### EXAMPLE 4 114 | `ConvertFrom-EZLog` is an utility function that is used to convert an EZLog file to a PowerShell object. 115 | 116 | ```PowerShell 117 | PS > $r = ConvertFrom-EZLog -Filepath C:\temp\logfile.log 118 | PS > $r 119 | 120 | Name Value 121 | ---- ----- 122 | Events {@{Date=3/30/2018 3:37:28 PM; Category=INF; Message=This is a test},... 123 | Footer {Duration, EndTime} 124 | Header {WhenGenerated, ScriptFullname, CurrentUser, CurrentComputer...} 125 | 126 | PS > $r.Header 127 | 128 | Name Value 129 | ---- ----- 130 | WhenGenerated 3/30/2018 3:36:55 PM 131 | ScriptFullname C:\Temp\script_example.ps1 132 | CurrentUser DEVWK1\Arnaud 133 | CurrentComputer DEVWK1 134 | OSArchitecture 64-bit 135 | OperatingSystem Microsoft Windows 10 Enterprise N 136 | 137 | 138 | PS > $r.footer 139 | 140 | Name Value 141 | ---- ----- 142 | Duration 00:16:01 143 | EndTime 3/30/2018 3:52:56 PM 144 | 145 | 146 | PS > $r.Events 147 | 148 | Date Category Message 149 | ---- -------- ------- 150 | 3/30/2018 3:37:28 PM INF This is a test 151 | 3/30/2018 3:51:56 PM INF This is a 2nd test 152 | 3/30/2018 3:52:15 PM WAR Attention needed! 153 | 154 | ``` 155 | 156 | As you can see, once a log file is converted into an object, it is super easy to manipulate the data without parsing the log with `Select-String` (grep equivalent). 157 | 158 | ### EXAMPLE 5 159 | `ConvertFrom-EZLog` combined with `ConvertTo-Json` could also be very useful. 160 | 161 | ```PowerShell 162 | PS > ConvertFrom-EZLog -Filepath C:\temp\logfile.log | ConvertTo-Json 163 | { 164 | "Events": [ 165 | { 166 | "Date": "\/Date(1522417048000)\/", 167 | "Category": "INF", 168 | "Message": "This is a test" 169 | }, 170 | { 171 | "Date": "\/Date(1522417916000)\/", 172 | "Category": "INF", 173 | "Message": "This is a 2nd test" 174 | }, 175 | { 176 | "Date": "\/Date(1522417935000)\/", 177 | "Category": "WAR", 178 | "Message": "Attention needed!" 179 | } 180 | ], 181 | "Footer": { 182 | "Duration": { 183 | "Ticks": 9610000000, 184 | "Days": 0, 185 | "Hours": 0, 186 | "Milliseconds": 0, 187 | "Minutes": 16, 188 | "Seconds": 1, 189 | "TotalDays": 0.011122685185185185, 190 | "TotalHours": 0.26694444444444443, 191 | "TotalMilliseconds": 961000, 192 | "TotalMinutes": 16.016666666666666, 193 | "TotalSeconds": 961 194 | }, 195 | "EndTime": "\/Date(1522417976000)\/" 196 | }, 197 | "Header": { 198 | "WhenGenerated": "\/Date(1522417015000)\/", 199 | "ScriptFullname": "C:\\Temp\\script_example.ps1", 200 | "CurrentUser": "DEVWK1\\Arnaud", 201 | "CurrentComputer": "DEVWK1", 202 | "OSArchitecture": "64-bit", 203 | "OperatingSystem": "Microsoft Windows 10 Enterprise N" 204 | } 205 | } 206 | ``` 207 | 208 | ### EXAMPLE 6 209 | A log module without a good rotation cmdlet wouldn't be complete, this is why I implemented one ;-) 210 | 211 | To rotate logs means to remove old log files. The periodicity of the rotation is passed to the `-Interval` parameter. You can specify the folowing values : `daily`, `weekly`, `monthly`, `yearly`. 212 | Instead of using `-Interval`, with `-Newest` you can simply specify the number of newest log files you want to keep. 213 | 214 | Moreover instead of just swipe out the old log files, you can choose to archive them in a Zip file. This is done with the `-ArchiveTo` and `-OverwriteArchive` parameters. The first parameter is used to specify the Zip file you want to create. If there's an existing file the logs will be appended by default. If you specify the switch `-OverwriteArchive`, as the name suggests, an existing archive file would be overwritten. 215 | 216 | ```PowerShell 217 | PS > Invoke-EZLogRotation -Path C:\LogFiles\*.log -Newest 15 -ArchiveTo C:\LogFiles\archive.zip 218 | ``` 219 | 220 | Keep only the latest 15 newest *.log files in the C:\LogFiles directory. Before deletion, older files 221 | will be archived into the C:\LogFiles\archive.zip. 222 | If the archive.zip file already exists, logs will be appended to it. 223 | 224 | ### EXAMPLE 7 225 | In this example, we will only keep the *.log files of the month in the C:\LogFiles directory. Older files will be deleted. 226 | 227 | ```PowerShell 228 | PS > Invoke-EZLogRotation -Path C:\LogFiles\*.log -Interval Monthly 229 | ``` 230 | 231 | --- 232 | ## Prerequisites 233 | 234 | Windows PowerShell v5+ 235 | PowerShell Core v6+ -------------------------------------------------------------------------------- /src/EZLog.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 5.1 2 | $ErrorActionPreference = 'Stop' 3 | Set-StrictMode -Version 2 4 | 5 | Add-Type -TypeDefinition @" 6 | public enum MsgCategory 7 | { 8 | INF = 0, 9 | WAR = 1, 10 | ERR = 2 11 | } 12 | 13 | public enum Interval 14 | { 15 | Daily = 0, 16 | Monthly = 2, 17 | Yearly = 3 18 | } 19 | "@ 20 | 21 | Function Write-EZLog 22 | { 23 | [cmdletBinding(DefaultParameterSetName="set2", SupportsShouldProcess=$False)] 24 | PARAM ( 25 | [parameter(Mandatory=$true, ParameterSetName="set2", ValueFromPipeline=$false, position=0)] 26 | [MsgCategory]$Category, 27 | 28 | [parameter(Mandatory=$true, ParameterSetName="set2", ValueFromPipeline=$false, position=1)] 29 | [Alias("Msg")] 30 | [String]$Message, 31 | 32 | [parameter(Mandatory=$true, ParameterSetName="set1", ValueFromPipeline=$false)] 33 | [Switch]$Header, 34 | 35 | [parameter(Mandatory=$true, ParameterSetName="set3", ValueFromPipeline=$false)] 36 | [Switch]$Footer, 37 | 38 | [parameter(Mandatory=$true, ValueFromPipeline=$false)] 39 | [String]$LogFile, 40 | 41 | [parameter(Mandatory=$false, ValueFromPipeline=$false)] 42 | [Char]$Delimiter = $( if ((Get-Culture).TextInfo.ListSeparator -eq ' ') {','} else {(Get-Culture).TextInfo.ListSeparator}), 43 | 44 | [parameter(Mandatory=$false, ValueFromPipeline=$false)] 45 | [Switch]$ToScreen=$false 46 | ) 47 | 48 | $Color = 'Cyan' 49 | 50 | $currentScriptName = $myinvocation.ScriptName 51 | $StartDate_str = Get-Date -UFormat "%Y-%m-%d %H:%M:%S" 52 | 53 | if ($isLinux -or $isMacOS) { 54 | $currentUser = $ENV:USER 55 | $currentComputer = uname -n 56 | $OSName = uname -s 57 | $OSArchi = uname -m 58 | $StrTerminator = "`r" 59 | } 60 | else { 61 | $currentUser = $ENV:USERDOMAIN + '\' + $ENV:USERNAME 62 | $currentComputer = $ENV:COMPUTERNAME 63 | $WmiInfos = Get-CimInstance win32_operatingsystem 64 | $OSName = $WmiInfos.caption 65 | $OSArchi = $WmiInfos.OSArchitecture 66 | $StrTerminator = "`r`n" 67 | } 68 | 69 | Switch ($PsCmdlet.ParameterSetName) 70 | { 71 | "set1" # Header 72 | { 73 | $Message = "+----------------------------------------------------------------------------------------+{0}" 74 | $Message += "Script fullname : $currentScriptName{0}" 75 | $Message += "When generated : $StartDate_str{0}" 76 | $Message += "Current user : $currentUser{0}" 77 | $Message += "Current computer : $currentComputer{0}" 78 | $Message += "Operating System : $OSName{0}" 79 | $Message += "OS Architecture : $OSArchi{0}" 80 | $Message += "+----------------------------------------------------------------------------------------+{0}" 81 | $Message += "{0}" 82 | 83 | $Message = $Message -f $StrTerminator 84 | # Log file creation. 85 | [VOID] (New-Item -ItemType File -Path $LogFile -Force) 86 | Add-Content -Path $LogFile -Value $Message -NoNewline 87 | 88 | break 89 | } 90 | 91 | "set2" # Body 92 | { 93 | $date = Get-Date -UFormat "%Y-%m-%d %H:%M:%S" 94 | switch ($Category) 95 | { 96 | INF { $Message = ("$date{0} INF{0} $Message{1}" -f $Delimiter, $StrTerminator); $Color = 'Cyan' ; break } 97 | WAR { $Message = ("$date{0} WAR{0} $Message{1}" -f $Delimiter, $StrTerminator); $Color = 'Yellow' ; break } 98 | ERR { $Message = ("$date{0} ERR{0} $Message{1}" -f $Delimiter, $StrTerminator); $Color = 'Red' ; break } 99 | } 100 | 101 | Add-Content -Path $LogFile -Value $Message -NoNewLine 102 | break 103 | } 104 | 105 | "set3" # Footer 106 | { 107 | # Extracting start date from the file header 108 | [VOID]( (Get-Content $LogFile -TotalCount 3)[-1] -match '^When generated\s*: (?\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})$' ) 109 | if ($null -eq $Matches.date) 110 | { 111 | throw "Cannot get the start date from the header. Please check if the file header is correctly formatted." 112 | } 113 | $StartDate = [DateTime]$Matches.date 114 | $EndDate = Get-Date 115 | $EndDate_str = Get-Date $EndDate -UFormat "%Y-%m-%d %H:%M:%S" 116 | 117 | $duration_TotalSeconds = [int](New-TimeSpan -Start $StartDate -End $EndDate | Select-Object -ExpandProperty TotalSeconds) 118 | $duration_TotalMinutes = (New-TimeSpan -Start $StartDate -End $EndDate | Select-Object -ExpandProperty TotalMinutes) 119 | $duration_TotalMinutes = [MATH]::Round($duration_TotalMinutes, 2) 120 | 121 | $Message = "{0}" 122 | $Message += "+----------------------------------------------------------------------------------------+{0}" 123 | $Message += "End time : $EndDate_str{0}" 124 | $Message += "Total duration (seconds) : $duration_TotalSeconds{0}" 125 | $Message += "Total duration (minutes) : $duration_TotalMinutes{0}" 126 | $Message += "+----------------------------------------------------------------------------------------+{0}" 127 | 128 | $Message = $Message -f $StrTerminator 129 | 130 | # Append the footer to the log file 131 | Add-Content -Path $LogFile -Value $Message -NoNewLine 132 | break 133 | } 134 | } # End switch 135 | 136 | if ($ToScreen) 137 | { 138 | Write-Host $Message -ForegroundColor $Color 139 | } 140 | } 141 | 142 | Function Get-Log 143 | { 144 | Param ($file) 145 | 146 | $content = Get-Content -Path $file 147 | $index = 0 148 | $sepPos = @() 149 | foreach ($line in $content) 150 | { 151 | if ($line -like '+-*-+') 152 | { 153 | $sepPos += $index 154 | } 155 | $index++ 156 | } 157 | 158 | $result = (Get-Content $file)[(($SepPos[1])+1)..(($SepPos[2])-1)] 159 | $result -ne '' # Blank lines exclusion 160 | } 161 | 162 | 163 | Function ConvertFrom-EZlog 164 | { 165 | Param ( 166 | [parameter(Mandatory=$true, ValueFromPipeline=$true, position=0)] 167 | [Alias("Path")] 168 | [string]$FilePath 169 | ) 170 | 171 | begin 172 | { 173 | 174 | } 175 | 176 | process 177 | { 178 | $result = @{ 179 | Header = @{ ScriptFullname = '' 180 | WhenGenerated = '' 181 | CurrentUser = '' 182 | CurrentComputer = '' 183 | OperatingSystem = '' 184 | OSArchitecture = '' 185 | } 186 | Events = @() 187 | Footer = @{ EndTime = '' 188 | Duration = '' 189 | } 190 | } 191 | 192 | $header = Get-Content -Path $FilePath | Select-Object -Skip 1 -First 6 193 | 194 | $result.Header.ScriptFullname = $( $null = $header[0] -match '(?.+?)(:\s{1})(?.+)?' 195 | if ( $matches ) 196 | { 197 | $matches.Value 198 | } 199 | ) 200 | $result.Header.WhenGenerated = $( $null = $header[1] -match '(?.+?)(:\s{1})(?.+)?' 201 | if ( $matches ) 202 | { 203 | [DateTime]($matches.Value) 204 | } 205 | ) 206 | 207 | $result.Header.CurrentUser = $( $null = $header[2] -match '(?.+?)(:\s{1})(?.+)?' 208 | if ( $matches ) 209 | { 210 | $matches.Value 211 | } 212 | ) 213 | 214 | $result.Header.CurrentComputer = $( $null = $header[3] -match '(?.+?)(:\s{1})(?.+)?' 215 | if ( $matches ) 216 | { 217 | $matches.Value 218 | } 219 | ) 220 | 221 | $result.Header.OperatingSystem = $( $null = $header[4] -match '(?.+?)(:\s{1})(?.+)?' 222 | if ($matches) 223 | { 224 | $matches.Value 225 | } 226 | ) 227 | $result.Header.OSArchitecture = $( $null = $header[5] -match '(?.+?)(:\s{1})(?.+)?' 228 | if ($matches) 229 | { 230 | $matches.Value 231 | } 232 | ) 233 | 234 | $footer = Get-Content -Path $FilePath | Select-Object -Skip 1 -Last 3 235 | 236 | $result.Footer.EndTime = $( $null = $footer[0] -match '(?.+?)(:\s{1})(?.+)?' 237 | if ($matches) 238 | { 239 | [DateTime]($matches.Value) 240 | } 241 | ) 242 | 243 | $result.Footer.Duration = New-TimeSpan -Start $result.Header.WhenGenerated -End $result.Footer.EndTime 244 | 245 | 246 | 247 | $LogMessages = Get-Log -file $FilePath 248 | $separator = $LogMessages[0][19] 249 | foreach ($log in $LogMessages) 250 | { 251 | #Handling of log messages with newline characters. 252 | 253 | #Check that the log line starts with a date time in expected format (%Y-%m-%d %H:%M:%S) and with one message category value. 254 | if($log -imatch "\d{4}-(0[1-9]|1[0-2])-\d{2} \d{2}:\d{2}:\d{2}$($separator)\s*($([MsgCategory]::GetNames([MsgCategory]) -join "|"))$($separator)\s*") 255 | { 256 | $res = $log -split $separator 257 | $result.Events += [PSCustomObject]@{ 258 | Date = $res[0] -as [DateTime] 259 | Category = $res[1].Trim() 260 | Message = $res[2].Trim() 261 | } 262 | } 263 | elseif($result.Events.Count -gt 0) 264 | { 265 | #Otherwise, append the line to the previous event message. 266 | $result.Events[$result.Events.Count - 1].Message += $log 267 | } 268 | } 269 | } 270 | 271 | end 272 | { 273 | $result 274 | } 275 | } 276 | 277 | Function Invoke-EZLogRotation 278 | { 279 | [cmdletBinding(DefaultParameterSetName='set1', SupportsShouldProcess=$False)] 280 | PARAM ( 281 | [parameter(Mandatory=$true, position=0)] 282 | [String]$Path, 283 | 284 | [parameter(Mandatory=$true, position=1)] 285 | [String]$Filter, 286 | 287 | [parameter(Mandatory=$true, ParameterSetName="set1", ValueFromPipeline=$false)] 288 | [Int]$Newest, 289 | 290 | [parameter(Mandatory=$true, ParameterSetName="set2", ValueFromPipeline=$false, position=1)] 291 | [Interval]$Interval, 292 | 293 | [parameter(Mandatory=$false)] 294 | [ValidateScript({$_ -like '*.zip'})] 295 | [String]$ArchiveTo, 296 | 297 | [parameter(Mandatory=$false)] 298 | [Switch]$OverwriteArchive 299 | ) 300 | 301 | Switch ($PSCmdlet.ParameterSetName) { 302 | 303 | 'Set1' { 304 | $filesToRemove = Get-ChildItem -Path $Path -Filter $Filter | Sort-Object -Property LastWriteTime -Descending | 305 | Select-Object -Skip $Newest 306 | } 307 | 308 | 'Set2' { 309 | Switch ($Interval) { 310 | 'Daily' { $filesToKeep = Get-ChildItem -Path $Path -Filter $Filter | 311 | Where-Object { $_.LastWriteTime.Year -eq (Get-Date).Year -and 312 | $_.LastWriteTime.Month -eq (Get-Date).Month -and 313 | $_.LastWriteTime.Day -eq (Get-Date).Day } 314 | $filesToRemove = Get-ChildItem "$Path\$Filter" -Exclude $filesToKeep 315 | Break 316 | } 317 | <# 'Weekly' { $filesToKeep = Get-ChildItem -Path $Path -Filter $Filter | 318 | Where-Object { $_.LastWriteTime -ge (Get-FirstDayOfWeekDate) -and 319 | $_.LastWriteTime -le (Get-Date) } 320 | $filesToRemove = Get-ChildItem "$Path\$Filter" -Exclude $filesToKeep 321 | Break 322 | } 323 | #> 324 | 'Monthly' { $filesToKeep = Get-ChildItem -Path $Path -Filter $Filter | 325 | Where-Object { $_.LastWriteTime -ge (Get-FirstDayOfMonthDate) -and 326 | $_.LastWriteTime -le (Get-Date) } 327 | $filesToRemove = Get-ChildItem "$Path\$Filter" -Exclude $filesToKeep 328 | Break 329 | } 330 | 'Yearly' { $filesToKeep = Get-ChildItem -Path $Path -Filter $Filter | 331 | Where-Object { $_.LastWriteTime.Year -eq (Get-Date).Year } 332 | $filesToRemove = Get-ChildItem "$Path\$Filter" -Exclude $filesToKeep 333 | Break 334 | } 335 | } 336 | } 337 | } 338 | 339 | if ($ArchiveTo -and $OverwriteArchive) { 340 | $filesToRemove | Compress-Archive -DestinationPath $ArchiveTo -CompressionLevel Optimal -Force 341 | } 342 | elseif ($ArchiveTo) { 343 | $filesToRemove | Compress-Archive -DestinationPath $ArchiveTo -CompressionLevel Optimal -Update 344 | } 345 | 346 | $filesToRemove | Remove-Item 347 | 348 | } 349 | 350 | Function Get-FirstDayOfWeek 351 | { 352 | 353 | (Get-Culture).DateTimeFormat.FirstDayOfWeek 354 | 355 | } 356 | 357 | Function Get-FirstDayOfWeekDate 358 | { 359 | Param ( [Datetime]$date = (Get-Date) ) 360 | 361 | if ( ( (Get-FirstDayOfWeek) -eq [DayOfWeek]::Monday) -and ($date.DayOfWeek -eq [DayOfWeek]::Sunday) ) { 362 | $nbJoursARetirer = 6 363 | } 364 | elseif ( ( (Get-FirstDayOfWeek) -eq [DayOfWeek]::Sunday) -and ($date.DayOfWeek -eq [DayOfWeek]::Sunday) ) { 365 | $nbJoursARetirer = 0 366 | } 367 | else { 368 | $nbJoursARetirer = [int]$date.DayOfWeek - [int](Get-FirstDayOfWeek) 369 | } 370 | 371 | $date = $date.AddDays(-$nbJoursARetirer) 372 | New-Object -TypeName datetime $date.Year, $date.Month, $date.Day, 0, 0, 0, 0 373 | } 374 | 375 | Function Get-FirstDayOfMonthDate 376 | { 377 | Param ( [Datetime]$date = (Get-Date) ) 378 | 379 | New-Object -TypeName datetime $date.Year, $date.Month, 1, 0, 0, 0, 0 380 | } -------------------------------------------------------------------------------- /src/EZLog.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module -Force (Join-Path $PSScriptRoot EZLog.psd1) 2 | 3 | InModuleScope "EZLog" { 4 | 5 | Describe "WriteEZLog function" { 6 | 7 | Function Test-EZLogDelimiter { 8 | Param ($delimiter) 9 | 10 | $logfile = Join-Path $TestDrive pester.log 11 | $PSDefaultParameterValues.Clear() 12 | $PSDefaultParameterValues.Add('Write-EZLog:LogFile', $logfile) 13 | $PSDefaultParameterValues.Add('Write-EZLog:Delimiter', $delimiter) 14 | 15 | Context "Separator '$delimiter'" { 16 | 17 | It "Creates a log file with a header in it." { 18 | Write-EZLog -Header 19 | Test-Path $logfile | Should Be $true 20 | } 21 | 22 | It "Test if the header was written correctly" { 23 | $r = Select-String -Path $logfile -Pattern '^\+\-*\+$' 24 | $r.count | Should Be 2 25 | } 26 | 27 | It "Writes an information into the log file." { 28 | Write-EZLog -Category INF -Message 'This is an info to be written in the log file' 29 | Get-Content $logfile | Select-String -Pattern ('INF' + $delimiter) -Quiet | Should Be $true 30 | } 31 | 32 | It "Writes a warning into the log file." { 33 | Write-EZLog -Category WAR -Message 'This is a warning to be written in the log file' 34 | Get-Content $logfile | Select-String -Pattern ('WAR' + $delimiter) -Quiet | Should Be $true 35 | } 36 | 37 | It "Writes an error into the log file." { 38 | Write-EZLog -Category ERR -Message 'This is an error to be written in the log file' 39 | Get-Content $logfile | Select-String -Pattern ('ERR' + $delimiter) -Quiet | Should Be $true 40 | } 41 | 42 | It "Writes the footer into the log file." { 43 | Write-EZLog -Footer 44 | Get-Content $logfile -Tail 1 | Should BeLike '+-*-+' 45 | } 46 | 47 | } # Context "separator validation" 48 | } 49 | 50 | Test-EZLogDelimiter -delimiter ',' 51 | Test-EZLogDelimiter -delimiter ';' 52 | Test-EZLogDelimiter -delimiter "`t" 53 | Test-EZLogDelimiter -delimiter "#" 54 | } # Write-EZLog Describe block 55 | 56 | Describe 'ConvertFromEZLog function' { 57 | 58 | Function Test-ConvertFromEZLog { 59 | Param ($delimiter) 60 | 61 | Context "Separator '$delimiter'" { 62 | 63 | $logfile = Join-Path $TestDrive pester.log 64 | $PSDefaultParameterValues.Clear() 65 | $PSDefaultParameterValues.Add('Write-EZLog:LogFile', $logfile) 66 | $PSDefaultParameterValues.Add('Write-EZLog:Delimiter', $delimiter) 67 | 68 | Write-EZLog -Header 69 | Write-EZLog -Category INF -Message 'This is an info to be written in the log file' 70 | Write-EZLog -Category WAR -Message 'This is a warning to be written in the log file' 71 | Write-EZLog -Category ERR -Message 'This is an error to be written in the log file' 72 | Write-EZLog -Footer 73 | 74 | $objLog = ConvertFrom-EZlog -FilePath $logFile 75 | 76 | It "It converts the log to a Hashtable" { 77 | $objLog | Should BeOfType [System.Collections.Hashtable] 78 | } 79 | 80 | It "It exists 3 properties in the Hashtable" { 81 | $objLog.keys.count | Should Be 3 82 | } 83 | 84 | $objLog.Header.psbase.keys | ForEach-Object { 85 | It "Header : property '$_' is not null " { 86 | $objLog.Header.$_ | Should Not BeNullOrEmpty 87 | } 88 | } 89 | 90 | $objLog.Footer.psbase.keys | ForEach-Object { 91 | It "Footer : property '$_' is not null " { 92 | $objLog.Footer.$_ | Should Not BeNullOrEmpty 93 | } 94 | } 95 | } # Context ConvertFrom-EZLog 96 | } 97 | 98 | Test-ConvertFromEZLog -delimiter ',' 99 | Test-ConvertFromEZLog -delimiter ';' 100 | Test-ConvertFromEZLog -delimiter "`t" 101 | Test-ConvertFromEZLog -delimiter "#" 102 | 103 | } # Describe block 104 | 105 | Describe 'Invoke-EZLogRotation' -Tag Rotate { 106 | 107 | Context 'Newest parameter' { 108 | 109 | BeforeEach { 110 | 1..50 | ForEach-Object { New-Item -Path "$TestDrive\file_$_.test" -ItemType file 111 | Start-Sleep -Milliseconds 25 } 112 | } 113 | AfterEach { 114 | Get-ChildItem -Path $TestDrive -Filter *.test | Remove-Item 115 | } 116 | 117 | It 'should only keep 20 files' { 118 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Newest 20 119 | (Get-ChildItem -Path $TestDrive -Filter *.test).count | Should BeExactly 20 120 | } 121 | 122 | It 'should only keep the newest files' { 123 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Newest 20 124 | # Check if the remaining files are the ones that should really be 125 | $arr1 = 31..50 | ForEach-Object {"file_$_.test"} 126 | $arr2 = Get-ChildItem -Path $TestDrive -Filter file_*.test | Sort-Object -Property LastWriteTime | Select-Object -ExpandProperty Name 127 | (Compare-Object -ReferenceObject $arr1 -DifferenceObject $arr2) | Should Be $Null 128 | } 129 | } # context 130 | 131 | Context 'Newest parameter combined with ArchiveTo parameter (no existing archive file)' { 132 | 133 | BeforeEach { 134 | 1..50 | Foreach-Object { New-Item -Path "$TestDrive\file_$_.test" -ItemType file 135 | Start-Sleep -Milliseconds 25 } 136 | } 137 | AfterEach { 138 | Get-ChildItem -Path $TestDrive -Filter *.test | Remove-Item 139 | } 140 | 141 | $archivePath = "$TestDrive\Archive.zip" 142 | It 'Should create an archive' { 143 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Newest 20 -ArchiveTo $archivePath 144 | Test-Path -Path $archivePath | Should Be $True 145 | } 146 | 147 | It 'The archive should be valid and should contain files' { 148 | Expand-Archive -Path $archivePath -DestinationPath $TestDrive\temp 149 | (Get-ChildItem -Path $TestDrive\temp).count | Should BeExactly 30 150 | } 151 | } # context 152 | 153 | 154 | Context 'Newest parameter combined with ArchiveTo parameter (archive file already exists)' { 155 | 156 | BeforeEach { 157 | # Archive creation. The goal is to check that the files are appended to it. 158 | 101..150 | ForEach-Object { New-Item -Path "$TestDrive\file_$_.test" -ItemType file 159 | Start-Sleep -Milliseconds 25 } 160 | $archivePath = "$TestDrive\Archive.zip" 161 | # 1st log rotation. We just keep the 15 newest files. 35 files should be archived. 162 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Newest 15 -ArchiveTo $archivePath 163 | 164 | # Adding 50 more files 165 | 1..50 | ForEach-Object { New-Item -Path "$TestDrive\file_$_.test" -ItemType file 166 | Start-Sleep -Milliseconds 25 } 167 | } 168 | 169 | AfterEach { 170 | # $host.EnterNestedPrompt() 171 | } 172 | 173 | $archivePath = "$TestDrive\Archive.zip" 174 | It 'Should append the logs to an existing archive' { 175 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Newest 20 -ArchiveTo $archivePath 176 | Expand-Archive -Path $archivePath -DestinationPath $TestDrive\temp 177 | (Get-ChildItem -Path $TestDrive\temp).count | Should BeExactly 80 178 | } 179 | } # context 180 | 181 | 182 | Context 'Newest parameter combined with ArchiveTo parameter plus OverwriteArchive switch (archive file already exists)' { 183 | 184 | BeforeEach { 185 | 186 | # Archive creation in order to check if it's overwrited as it should. 187 | 101..150 | ForEach-Object { New-Item -Path "$TestDrive\file_$_.test" -ItemType file 188 | Start-Sleep -Milliseconds 25 } 189 | $archivePath = "$TestDrive\Archive.zip" 190 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Newest 15 -ArchiveTo $archivePath 191 | 192 | # Creating 50 additionnal files 193 | 1..50 | ForEach-Object { New-Item -Path "$TestDrive\file_$_.test" -ItemType file 194 | Start-Sleep -Milliseconds 25 } 195 | } 196 | 197 | AfterEach { 198 | } 199 | 200 | $archivePath = "$TestDrive\Archive.zip" 201 | It 'Should overwrite an existing archive' { 202 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Newest 20 -ArchiveTo $archivePath -OverwriteArchive 203 | Expand-Archive -Path $archivePath -DestinationPath $TestDrive\temp 204 | (Get-ChildItem -Path $TestDrive\temp).count | Should BeExactly 45 205 | } 206 | } # context 207 | } # Describe 208 | 209 | Describe 'Daily Rotation' -Tag daily { 210 | Context 'Rotates the logs on a daily interval.' { 211 | 212 | BeforeEach { 213 | 1..72 | Foreach-Object { New-Item -Path "$TestDrive\file_$_.test" -ItemType file} 214 | $date = '2018/01/15 12:00:00' -as [datetime] 215 | Get-ChildItem $TestDrive\*.test | Sort-Object -Property LastWriteTime | Foreach-Object {$i=0} {$_.LastWriteTime = $date.AddHours(-$i); $i++} 216 | } 217 | 218 | AfterEach { 219 | Remove-Item -Path $TestDrive\* -force 220 | } 221 | 222 | Mock Get-Date { '2018/01/14 12:00:00' -as [datetime] } 223 | 224 | It 'There should be 24 files left in the directory after invoking the rotation function' { 225 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Interval Daily 226 | 227 | # There should be 24 files left 228 | (Get-ChildItem -Path $TestDrive -Filter *.test).count | Should BeExactly 24 229 | } 230 | 231 | It 'The Day property of the remaining files should be unique' { 232 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Interval Daily 233 | @(Get-ChildItem -Path $TestDrive -Filter *.test | Select-Object -ExpandProperty LastWriteTime | Select -ExpandProperty day -Unique).count | Should BeExactly 1 234 | } 235 | 236 | It 'The Day property of the remaining files should be 14' { 237 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Interval Daily 238 | Get-ChildItem -Path $TestDrive -Filter *.test | Select-Object -ExpandProperty LastWriteTime | Select -ExpandProperty day -Unique | Should BeExactly 14 239 | } 240 | } # Context 241 | } 242 | 243 | <# Describe 'Weekly Rotation' -Tag weekly { 244 | Context 'Rotates the logs on a weekly interval.' { 245 | 246 | BeforeEach { 247 | 1..500 | Foreach-Object { New-Item -Path "$TestDrive\file_$_.test" -ItemType file } 248 | $date = '2018/01/15 12:00:00' -as [datetime] 249 | Get-ChildItem $TestDrive\*.test | Sort-Object -Property LastWriteTime | Foreach-Object {$i=0} {$_.LastWriteTime = $date.AddHours(-$i); $i++} 250 | } 251 | 252 | AfterEach { 253 | Remove-Item -Path $TestDrive\* -force 254 | } 255 | 256 | Mock Get-Date { '2018/01/14 12:00:00' -as [datetime] } 257 | 258 | it 'Should left only files created during the week' { 259 | $host.EnterNestedPrompt() 260 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Interval Weekly 261 | $DateDayOfWeek = Get-FirstDayOfWeekDate -date (Get-Date) 262 | $res = Get-ChildItem -Path $TestDrive -Filter *.test | Where-Object { $_.LastWriteTime -ge $DateDayOfWeek } 263 | $res.count | Should Be 157 264 | } 265 | } # Context 266 | } 267 | #> 268 | 269 | Describe 'Get-FirstDayOfWeekDate on countries where Monday is the first day of the week' { 270 | 271 | Mock Get-FirstDayOfWeek { [dayofweek]::Monday } 272 | 273 | Context 'Monday' { 274 | It 'Should return Monday of the same day' { 275 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 22 -Month 01 -Year 2018) 276 | $res.day | Should Be 22 277 | } 278 | } 279 | 280 | Context 'Tuesday' { 281 | It 'Should return Monday of the same week' { 282 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 23 -Month 01 -Year 2018) 283 | $res.day | Should Be 22 284 | } 285 | } 286 | 287 | Context 'Wednesday' { 288 | It 'Should return Monday of the same week' { 289 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 24 -Month 01 -Year 2018) 290 | $res.day | Should Be 22 291 | } 292 | } 293 | 294 | Context 'Thursday' { 295 | It 'Should return Monday of the same week' { 296 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 25 -Month 01 -Year 2018) 297 | $res.day | Should Be 22 298 | } 299 | } 300 | 301 | Context 'Friday' { 302 | It 'Should return Monday of the same week' { 303 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 26 -Month 01 -Year 2018) 304 | $res.day | Should Be 22 305 | } 306 | } 307 | 308 | Context 'Saturday' { 309 | It 'Should return Monday of the same week' { 310 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 27 -Month 01 -Year 2018) 311 | $res.day | Should Be 22 312 | } 313 | } 314 | 315 | Context 'Sunday' { 316 | It 'Should return Monday of the same week' { 317 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 28 -Month 01 -Year 2018) 318 | $res.day | Should Be 22 319 | } 320 | } 321 | } # Describe 322 | 323 | Describe 'Get-FirstDayOfWeekDate on countries where Sunday is the first day of the week' { 324 | 325 | Mock Get-FirstDayOfWeek { [dayofweek]::Sunday } 326 | 327 | Context 'Sunday' { 328 | It 'Should return Sunday of the same day' { 329 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 21 -Month 01 -Year 2018) 330 | $res.day | Should Be 21 331 | } 332 | } 333 | 334 | Context 'Monday' { 335 | It 'Should return Sunday of the same week ' { 336 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 22 -Month 01 -Year 2018) 337 | $res.day | Should Be 21 338 | } 339 | } 340 | 341 | Context 'Tuesday' { 342 | It 'Should return Sunday of the same week' { 343 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 23 -Month 01 -Year 2018) 344 | $res.day | Should Be 21 345 | } 346 | } 347 | 348 | Context 'Wednesday' { 349 | It 'Should return Sunday of the same week' { 350 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 24 -Month 01 -Year 2018) 351 | $res.day | Should Be 21 352 | } 353 | } 354 | 355 | Context 'Thursday' { 356 | It 'Should return Sunday of the same week' { 357 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 25 -Month 01 -Year 2018) 358 | $res.day | Should Be 21 359 | } 360 | } 361 | 362 | Context 'Friday' { 363 | It 'Should return Sunday of the same week' { 364 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 26 -Month 01 -Year 2018) 365 | $res.day | Should Be 21 366 | } 367 | } 368 | 369 | Context 'Saturday' { 370 | It 'Should return Sunday of the same week' { 371 | $res = Get-FirstDayOfWeekDate -Date (Get-Date -Day 27 -Month 01 -Year 2018) 372 | $res.day | Should Be 21 373 | } 374 | } 375 | } # Describe 376 | 377 | Describe 'Monthly Rotation' -Tag monthly { 378 | Context 'Rotates the logs on a monthly interval.' { 379 | 380 | BeforeEach { 381 | 1..500 | Foreach-Object { New-Item -Path "$TestDrive\file_$_.test" -ItemType file } 382 | $date = '2018/01/15 12:00:00' -as [datetime] 383 | Get-ChildItem $TestDrive\*.test | Sort-Object -Property LastWriteTime | Foreach-Object {$i=0} {$_.LastWriteTime = $date.AddHours(-$i); $i++} 384 | } 385 | 386 | AfterEach { 387 | Remove-Item -Path $TestDrive\* -force 388 | } 389 | 390 | Mock Get-Date { '2018/01/14 12:00:00' -as [datetime] } 391 | 392 | it 'Should be left only files created since the begining of the month => 325 files' { 393 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Interval Monthly 394 | $DateFirstDayOfMonth = Get-FirstDayOfMonthDate -date (Get-Date) 395 | 396 | $res = Get-ChildItem -Path $TestDrive -Filter *.test | Where-Object { $_.LastWriteTime -ge $DateFirstDayOfMonth } 397 | $res.count | Should Be 325 398 | } 399 | 400 | it 'All files should have the same month value in the LastWriteTime property' { 401 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Interval Monthly 402 | $month = @(Get-ChildItem -Path $TestDrive -Filter *.test | Select-Object -Property @{n='month';e={$_.LastWriteTime.Month}} -Unique).count 403 | 404 | $month | Should Be 1 405 | 406 | } 407 | } # Context 408 | } 409 | 410 | Describe 'Yearly Rotation' { 411 | Context 'Rotates the logs on a yearly interval.' { 412 | 413 | BeforeEach { 414 | 1..500 | Foreach-Object { New-Item -Path "$TestDrive\file_$_.test" -ItemType file } 415 | $date = '2019/01/01 00:00:00' -as [datetime] 416 | Get-ChildItem $TestDrive\*.test | Sort-Object -Property LastWriteTime | Foreach-Object {$i=1} {$_.LastWriteTime = $date.AddDays(-$i); $i++} 417 | } 418 | 419 | AfterEach { 420 | Remove-Item -Path $TestDrive\* -force -recurse 421 | } 422 | 423 | Mock Get-Date { '2018/01/14 12:00:00' -as [datetime] } 424 | 425 | it 'Should be left only files created since the beginning of the year => 365 files' { 426 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Interval Yearly 427 | $DateFirstDayOfYear = '01/01/2018 00:00:00' -as [datetime] 428 | 429 | $res = Get-ChildItem -Path $TestDrive -Filter *.test | Where-Object { $_.LastWriteTime -ge $DateFirstDayOfYear } 430 | $res.count | Should Be 365 431 | } 432 | 433 | it 'All files should have the same year value in the LastWriteTime property' { 434 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Interval Yearly 435 | $year = @(Get-ChildItem -Path $TestDrive -Filter *.test | Select-Object -Property @{n='year';e={$_.LastWriteTime.Year}} -Unique).count 436 | 437 | $year | Should Be 1 438 | } 439 | 440 | it 'Should create an archive file' { 441 | $archivePath = "$TestDrive\Archive.zip" 442 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Interval Yearly -ArchiveTo $archivePath 443 | Test-Path -Path $archivePath | Should Be $True 444 | 445 | } 446 | 447 | it 'Archive should contain files' { 448 | $archivePath = "$TestDrive\Archive.zip" 449 | Invoke-EZLogRotation -Path $TestDrive -Filter *.test -Interval Yearly -ArchiveTo $archivePath 450 | Expand-Archive -Path $archivePath -DestinationPath $TestDrive\temp 451 | (Get-ChildItem -Path $TestDrive\temp).count | Should Not Be 0 452 | } 453 | 454 | 455 | } # Context 456 | 457 | } # Describe Yearly 458 | 459 | } -------------------------------------------------------------------------------- /src/en-US/EZLog-help.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ConvertFrom-EZlog 6 | ConvertFrom 7 | EZlog 8 | 9 | Cmdlet that convert an EZLog file to a set of objects. 10 | 11 | 12 | 13 | This cmdlet allows from a log file generated by EZLog to get an object. The goal is to be able to easily filter on events with a single Where-Object and get to the info stored in the header and in the footer. 14 | Furthermore it eases the ability to transform the data to JSON if piped to ConvertTo-JSON. 15 | 16 | 17 | 18 | ConvertFrom-EZlog 19 | 20 | FilePath 21 | 22 | Specify the log file's path. 23 | 24 | String 25 | 26 | String 27 | 28 | 29 | None 30 | 31 | 32 | 33 | 34 | 35 | FilePath 36 | 37 | Specify the log file's path. 38 | 39 | String 40 | 41 | String 42 | 43 | 44 | None 45 | 46 | 47 | 48 | 49 | 50 | 51 | AUTHOR: Arnaud PETITJEAN - arnaud@powershell-scripting.com LASTEDIT: 2016/11/15 52 | 53 | 54 | 55 | 56 | -------------------------- EXAMPLE 1 -------------------------- 57 | ConvertFrom-EZlog -FilePath C:\temp\mylog.log 58 | 59 | Returns an object from the log file. 60 | 61 | 62 | 63 | -------------------------- EXAMPLE 2 -------------------------- 64 | ConvertFrom-EZlog -FilePath C:\temp\mylog.log | ConvertTo-JSON 65 | 66 | Get a JSON format from a logfile. 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Invoke-EZLogRotation 75 | Invoke 76 | EZLogRotation 77 | 78 | Clean up old log files in order to keep only the most recent ones. 79 | 80 | 81 | 82 | Ancient logs files are either deleted or archived into a Zip file. 83 | Options are available to specify how many newest files to keep. It's also possible to determine a time interval for the logs to keep (daily, monthly, yearly) 84 | 85 | 86 | 87 | Invoke-EZLogRotation 88 | 89 | Path 90 | 91 | Directory containing the logs to rotate. 92 | 93 | String 94 | 95 | String 96 | 97 | 98 | None 99 | 100 | 101 | Filter 102 | 103 | Pattern to identify the logs to rotate. Ex : .log, ezlog*.txt, etc. 104 | 105 | String 106 | 107 | String 108 | 109 | 110 | None 111 | 112 | 113 | Newest 114 | 115 | Specify how many files to keep in the directory. The files are sorted by the LastWriteTime attribute and only the newest files determined by this parameter are kept. Other files are deleted or archived. 116 | 117 | Int32 118 | 119 | Int32 120 | 121 | 122 | 0 123 | 124 | 125 | ArchiveTo 126 | 127 | Indicate if the old logs need to be archived in a Zip before before deletion. 128 | If not specified, old logs are deleted. 129 | If specified, you must indicate a file path containing the .zip extension. Eg. : C:\logs\archive.zip 130 | If the archive file already exists, logs will be append to it. If you want to overwrite it you can use the -OverwriteArchive switch. 131 | 132 | String 133 | 134 | String 135 | 136 | 137 | None 138 | 139 | 140 | OverwriteArchive 141 | 142 | Works in association with -ArchiveTo. If specified, it overwrites an archive if it already exists. 143 | 144 | 145 | SwitchParameter 146 | 147 | 148 | False 149 | 150 | 151 | 152 | Invoke-EZLogRotation 153 | 154 | Path 155 | 156 | Directory containing the logs to rotate. 157 | 158 | String 159 | 160 | String 161 | 162 | 163 | None 164 | 165 | 166 | Filter 167 | 168 | Pattern to identify the logs to rotate. Ex : .log, ezlog*.txt, etc. 169 | 170 | String 171 | 172 | String 173 | 174 | 175 | None 176 | 177 | 178 | Interval 179 | 180 | Specify the periodicy of the rotation. Possible values are : Daily, Monthly, Yearly 181 | Daily : Keep only the logs of the day Monthly : Keep only the logs of the month Yearly : Keep only the logs of the year 182 | 183 | 184 | Daily 185 | Monthly 186 | Yearly 187 | 188 | Interval 189 | 190 | Interval 191 | 192 | 193 | None 194 | 195 | 196 | ArchiveTo 197 | 198 | Indicate if the old logs need to be archived in a Zip before before deletion. 199 | If not specified, old logs are deleted. 200 | If specified, you must indicate a file path containing the .zip extension. Eg. : C:\logs\archive.zip 201 | If the archive file already exists, logs will be append to it. If you want to overwrite it you can use the -OverwriteArchive switch. 202 | 203 | String 204 | 205 | String 206 | 207 | 208 | None 209 | 210 | 211 | OverwriteArchive 212 | 213 | Works in association with -ArchiveTo. If specified, it overwrites an archive if it already exists. 214 | 215 | 216 | SwitchParameter 217 | 218 | 219 | False 220 | 221 | 222 | 223 | 224 | 225 | Path 226 | 227 | Directory containing the logs to rotate. 228 | 229 | String 230 | 231 | String 232 | 233 | 234 | None 235 | 236 | 237 | Filter 238 | 239 | Pattern to identify the logs to rotate. Ex : .log, ezlog*.txt, etc. 240 | 241 | String 242 | 243 | String 244 | 245 | 246 | None 247 | 248 | 249 | Newest 250 | 251 | Specify how many files to keep in the directory. The files are sorted by the LastWriteTime attribute and only the newest files determined by this parameter are kept. Other files are deleted or archived. 252 | 253 | Int32 254 | 255 | Int32 256 | 257 | 258 | 0 259 | 260 | 261 | Interval 262 | 263 | Specify the periodicy of the rotation. Possible values are : Daily, Monthly, Yearly 264 | Daily : Keep only the logs of the day Monthly : Keep only the logs of the month Yearly : Keep only the logs of the year 265 | 266 | Interval 267 | 268 | Interval 269 | 270 | 271 | None 272 | 273 | 274 | ArchiveTo 275 | 276 | Indicate if the old logs need to be archived in a Zip before before deletion. 277 | If not specified, old logs are deleted. 278 | If specified, you must indicate a file path containing the .zip extension. Eg. : C:\logs\archive.zip 279 | If the archive file already exists, logs will be append to it. If you want to overwrite it you can use the -OverwriteArchive switch. 280 | 281 | String 282 | 283 | String 284 | 285 | 286 | None 287 | 288 | 289 | OverwriteArchive 290 | 291 | Works in association with -ArchiveTo. If specified, it overwrites an archive if it already exists. 292 | 293 | SwitchParameter 294 | 295 | SwitchParameter 296 | 297 | 298 | False 299 | 300 | 301 | 302 | 303 | 304 | 305 | AUTHOR: Arnaud PETITJEAN LASTEDIT: 2018/04/03 306 | 307 | 308 | 309 | 310 | -------------------------- EXAMPLE 1 -------------------------- 311 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Newest 15 312 | 313 | Only keeps the latest 15 newest *.log files in the C:\LogFiles directory. Older files will be deleted. 314 | 315 | 316 | 317 | -------------------------- EXAMPLE 2 -------------------------- 318 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Newest 15 -ArchiveTo C:\LogFiles\archive.zip 319 | 320 | Only keeps the latest 15 newest *.log files in the C:\LogFiles directory. Before deletion, older files will be archived into the C:\LogFiles\archive.zip. If the archive.zip file already exists, logs will be appended to it. 321 | 322 | 323 | 324 | -------------------------- EXAMPLE 3 -------------------------- 325 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Newest 15 -ArchiveTo C:\LogFiles\archive.zip -OverwriteArchive 326 | 327 | Only keeps the latest 15 newest *.log files in the C:\LogFiles directory. Before deletion, older files will be archived into the C:\LogFiles\archive.zip. If the archive.zip file already exists it will be overwritten. 328 | 329 | 330 | 331 | -------------------------- EXAMPLE 4 -------------------------- 332 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Interval Daily 333 | 334 | Only keeps the *.log files of the day in the C:\LogFiles directory. Older files will be deleted. 335 | 336 | 337 | 338 | -------------------------- EXAMPLE 5 -------------------------- 339 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Interval Monthly 340 | 341 | Only keeps the *.log files of the month in the C:\LogFiles directory. Older files will be deleted. 342 | 343 | 344 | 345 | -------------------------- EXAMPLE 6 -------------------------- 346 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Interval Monthly -ArchiveTo C:\LogFiles\archive.zip -Overwrite 347 | 348 | Only keeps the *.log files of the month in the C:\LogFiles directory. Older files will be archived monthly. 349 | 350 | 351 | 352 | -------------------------- EXAMPLE 7 -------------------------- 353 | Invoke-EZLogRotation -Path C:\LogFiles\*.log -Interval Yearly 354 | 355 | Only keeps the .log files of the current year in the C:\LogFiles directory matching the pattern .log. Older files will be deleted. 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | Write-EZLog 364 | Write 365 | EZLog 366 | 367 | Utility cmdlet to write logs to disk in an easy and pragmatic way. 368 | 369 | 370 | 371 | This cmdlet allows to write timestamped and nice formatted logs with a header and footer. It also allows to specify if the log entry being written is an info, a warning or an error. 372 | The header contains the following information : - full script path of the caller, 373 | - account under the script was run, 374 | - computer name of the machine whose executed the script, 375 | - and more... 376 | 377 | The footer contains the elapsed time from the beginning of the log session. 378 | 379 | 380 | 381 | Write-EZLog 382 | 383 | Category 384 | 385 | Category can be one of the following value : INF, WAR, ERR 386 | 387 | 388 | INF 389 | WAR 390 | ERR 391 | 392 | MsgCategory 393 | 394 | MsgCategory 395 | 396 | 397 | None 398 | 399 | 400 | Message 401 | 402 | Specify the content of the data to log. 403 | 404 | String 405 | 406 | String 407 | 408 | 409 | None 410 | 411 | 412 | LogFile 413 | 414 | Path to the log file to be created. 415 | 416 | String 417 | 418 | String 419 | 420 | 421 | None 422 | 423 | 424 | Delimiter 425 | 426 | Specify a delimiter to be used in order to separate the fields in a log entry. 427 | 428 | Char 429 | 430 | Char 431 | 432 | 433 | $( if ((Get-Culture).TextInfo.ListSeparator -eq ' ') {','} else {(Get-Culture).TextInfo.ListSeparator}) 434 | 435 | 436 | ToScreen 437 | 438 | Displays the logs in the log file and in the console. 439 | 440 | 441 | SwitchParameter 442 | 443 | 444 | False 445 | 446 | 447 | 448 | Write-EZLog 449 | 450 | Header 451 | 452 | Mandatory switch to start a log session. 453 | 454 | 455 | SwitchParameter 456 | 457 | 458 | False 459 | 460 | 461 | LogFile 462 | 463 | Path to the log file to be created. 464 | 465 | String 466 | 467 | String 468 | 469 | 470 | None 471 | 472 | 473 | Delimiter 474 | 475 | Specify a delimiter to be used in order to separate the fields in a log entry. 476 | 477 | Char 478 | 479 | Char 480 | 481 | 482 | $( if ((Get-Culture).TextInfo.ListSeparator -eq ' ') {','} else {(Get-Culture).TextInfo.ListSeparator}) 483 | 484 | 485 | ToScreen 486 | 487 | Displays the logs in the log file and in the console. 488 | 489 | 490 | SwitchParameter 491 | 492 | 493 | False 494 | 495 | 496 | 497 | Write-EZLog 498 | 499 | Footer 500 | 501 | Mandatory switch to end a log session. If you omit to close your log session, you won't know how much time your script was running. 502 | 503 | 504 | SwitchParameter 505 | 506 | 507 | False 508 | 509 | 510 | LogFile 511 | 512 | Path to the log file to be created. 513 | 514 | String 515 | 516 | String 517 | 518 | 519 | None 520 | 521 | 522 | Delimiter 523 | 524 | Specify a delimiter to be used in order to separate the fields in a log entry. 525 | 526 | Char 527 | 528 | Char 529 | 530 | 531 | $( if ((Get-Culture).TextInfo.ListSeparator -eq ' ') {','} else {(Get-Culture).TextInfo.ListSeparator}) 532 | 533 | 534 | ToScreen 535 | 536 | Displays the logs in the log file and in the console. 537 | 538 | 539 | SwitchParameter 540 | 541 | 542 | False 543 | 544 | 545 | 546 | 547 | 548 | Category 549 | 550 | Category can be one of the following value : INF, WAR, ERR 551 | 552 | MsgCategory 553 | 554 | MsgCategory 555 | 556 | 557 | None 558 | 559 | 560 | Message 561 | 562 | Specify the content of the data to log. 563 | 564 | String 565 | 566 | String 567 | 568 | 569 | None 570 | 571 | 572 | Header 573 | 574 | Mandatory switch to start a log session. 575 | 576 | SwitchParameter 577 | 578 | SwitchParameter 579 | 580 | 581 | False 582 | 583 | 584 | Footer 585 | 586 | Mandatory switch to end a log session. If you omit to close your log session, you won't know how much time your script was running. 587 | 588 | SwitchParameter 589 | 590 | SwitchParameter 591 | 592 | 593 | False 594 | 595 | 596 | LogFile 597 | 598 | Path to the log file to be created. 599 | 600 | String 601 | 602 | String 603 | 604 | 605 | None 606 | 607 | 608 | Delimiter 609 | 610 | Specify a delimiter to be used in order to separate the fields in a log entry. 611 | 612 | Char 613 | 614 | Char 615 | 616 | 617 | $( if ((Get-Culture).TextInfo.ListSeparator -eq ' ') {','} else {(Get-Culture).TextInfo.ListSeparator}) 618 | 619 | 620 | ToScreen 621 | 622 | Displays the logs in the log file and in the console. 623 | 624 | SwitchParameter 625 | 626 | SwitchParameter 627 | 628 | 629 | False 630 | 631 | 632 | 633 | 634 | 635 | 636 | AUTHOR: Arnaud PETITJEAN - apetitjean@start-scripting.io LASTEDIT: 2023/11/30 637 | 638 | 639 | 640 | 641 | -------------------------- EXAMPLE 1 -------------------------- 642 | # First thing to do is write a header and define a log file where the data will be written to. 643 | 644 | Write-EZLog -Header -LogFile C:\logs\mylogfile.log 645 | 646 | 647 | 648 | 649 | 650 | -------------------------- EXAMPLE 2 -------------------------- 651 | # Next, anywhere in your script when you need to write a log, do one of the folowing command: 652 | 653 | Write-EZLog -Category INF -Message 'This is an info to be written in the log file' 654 | Write-EZLog -Category WAR -Message 'This is a warning to be written in the log file' 655 | Write-EZLog -Category ERR -Message 'This is an error to be written in the log file' 656 | 657 | 658 | 659 | 660 | 661 | -------------------------- EXAMPLE 3 -------------------------- 662 | # Finaly, to close your logfile you need to write a footer, just do that: 663 | 664 | Write-EZLog -Footer 665 | 666 | 667 | 668 | 669 | 670 | -------------------------- EXAMPLE 4 -------------------------- 671 | # If you want to see the logs in the PowerShell console whereas they are still written to disk, you can specify the -ToScreen switch. 672 | # Info entries will be written in cyan color, Yellow for warnings, and Red for the errors. 673 | 674 | Write-EZLog -Category WAR -Message 'This is a warning to be written in the log file' -ToScreen 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | See my Github repository 683 | https://github.com/apetitjean/EZLog 684 | 685 | 686 | 687 | --------------------------------------------------------------------------------