Answers.Body: <p>Another perhaps simpler approach is to write to your own log file without using the Craft logger at all.</p>
  
  <pre><code>$file = Craft::getAlias('@storage/logs/pluginhandle.log');
  $log = date('Y-m-d H:i:s').' '.$message."\n";
  
  \craft\helpers\FileHelper::writeToFile($file, $log, ['append' =&gt; true]);
  </code></pre>
  
  <p>UPDATE:</p>
  
  <p>This logic has been put into a helper class for modules and plugins in Craft CMS:
  <a href="https://github.com/putyourlightson/craft-log-to-file" rel="nofollow noreferrer">https://github.com/putyourlightson/craft-log-to-file</a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-10-05T22:28:06.927Z
Answers.Text: That's pretty slick! Just circumvent the whole system.
Answers.UserDisplayName: Lindsey D
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-07-21T02:44:14.633Z
Answers.Text: Just remember, there's a reason why Yii2's logging system jumps through the hoops that it does.
Answers.UserDisplayName: andrew.welch
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-12T00:02:27.040Z
Answers.Text: Thank you for this Ben!
Answers.UserDisplayName: Anna_MediaGirl
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-12T06:06:46.947Z
Answers.Text: Sure thing Anna, I now use this approach for all plugins with this helper class:
  https://github.com/putyourlightson/craft-log-to-file
Answers.UserDisplayName: Ben Croker
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-10-05T18:50:01.983Z
Answers.LastActivityDate: 2020-02-12T06:05:59.830Z
Answers.LastEditDate: 2020-02-12T06:05:59.830Z
Answers.UserDisplayName: Ben Croker
Answers.Body: <p>Adding this for posterity, for any future-traveller who happens to come along.</p>
  
  <p>Here's everything you need to know about making a custom logger for Craft CMS:</p>
  
  <p><a href="https://nystudio107.com/blog/creating-a-custom-logger-for-craft-cms" rel="nofollow noreferrer">Creating a Custom Logger for Craft CMS</a></p>
  
  <p>And then once you have a log file, you need to know how to read it:</p>
  
  <p><a href="https://nystudio107.com/blog/zen-and-the-art-of-craft-cms-log-file-reading" rel="nofollow noreferrer">Zen and the Art of Craft CMS Log File Reading</a></p>
  
  <p>Godspeed, future traveller!</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-12T20:59:15.393Z
Answers.LastActivityDate: 2020-02-12T20:59:15.393Z
Answers.UserDisplayName: andrew.welch
Answers.Body: <h3>Edit 2</h3>
  
  <p>I came up with a far far far better approach after a little brainstorming. I'll keep my old answer here but you should probably just use the first snipped.</p>
  
  <p>In your main Pluginfile.php</p>
  
  <pre class="lang-php prettyprint-override"><code>public static function log($message){
      Craft::getLogger()-&gt;log($message, \yii\log\Logger::LEVEL_INFO, 'your-plugin-handle');
  }
  
  public function init(){
      $fileTarget = new \craft\log\FileTarget([
          'logFile' =&gt; __DIR__ . '/pluginName.log', // &lt;--- path of the log file
          'categories' =&gt; ['your-plugin-handle'] // &lt;--- categories in the file
      ]);
      // include the new target file target to the dispatcher
      Craft::getLogger()-&gt;dispatcher-&gt;targets[] = $fileTarget;
      ....
  }
  </code></pre>
  
  <p>Explanation: <code>categories</code> is an array of all categories that should be in the log file. You usually want to allow only categories of your own plugin (you have to use an unique identifier in case certain other developers try to add the same category). Whenever you want to log something with the Craft/Yii <code>log</code> method that match one of your given categories in the array it will be logged in your file as well.</p>
  
  <h3>Old answer</h3>
  
  <p>Create this file somewhere in your plugin</p>
  
  <h3>FileTarget</h3>
  
  <pre class="lang-php prettyprint-override"><code>class FileTarget extends \yii\log\FileTarget{
  
      // an array of categories that should be logged
      // note: your target receives all `Yii::log()` messages
      // but you can filter them with this array
      // if you want to track all messages of type 'application' as well
      // just include it in the array
      public $categories = ['a-category-that-you-would-like-to-log']; //&lt;- usually your plugin handle or something
  
      // set the file path
      public function setLogFile($path = __DIR__){
          // I'm lazy so I just use the current location since it's in my 'src/' folder anyway 
          // you can use Crafts default folders or whatever you like
          $this-&gt;logFile = $path . '/test.log';
          return $this;
      }
  
      // Optional -&gt; a callback that formats your messages
      // remove this function if there is
      // no formatting needed or if you want to use the default
      public function formatMessage($message)
      {
          list($text, $level, $category, $timestamp) = $message;
          $level = 'Your fancy plugin Name';
  
          if ($category == 'a-category-that-you-would-like-to-log') {
              return date('Y-m-d H:i:s', $timestamp) . " [$level][$category] $text";
          }
      }
  }
  </code></pre>
  
  <h3>In your Plugin main file</h3>
  
  <pre class="lang-php prettyprint-override"><code>public static $_fileTarget;
  
  public static function log($message){
      if(self::$_fileTarget === null){
          /** @var FileTarget _fileTarget */
          self::$_fileTarget = Craft::createObject('namespace\pluginhandle\filetarget');
          // set the path
          self::$_fileTarget-&gt;setLogFile();
          // include your target to the current dispatcher targets 
          // -&gt; all messages are tracked in your target as well. 
          Craft::getLogger()-&gt;dispatcher-&gt;targets[] = self::$_fileTarget;
      }
  
      // just use the default Craft/Yii logging method but with your category
      Craft::getLogger()-&gt;log($message, \yii\log\Logger::LEVEL_INFO, 'a-category-that-you-would-like-to-log');
  }
  </code></pre>
  
  <h3>Usage</h3>
  
  <pre class="lang-php prettyprint-override"><code>Plugin::log('Lorem ipsum');
  Craft::getLogger()-&gt;log('Lorem ipsum', \yii\log\Logger::LEVEL_INFO, 'a-category-that-you-would-like-to-log');
  Craft::info('Lorem ipsum', 'a-category-that-you-would-like-to-log');
  </code></pre>
  
  <p>Maybe we could create a feature/pull request in order to create this feature by default. So every Plugin receives it's own category (by plugin handle) and if these categories are recognized the logger logs them in a separate file</p>
  
  <h3>Edit (thanks Andrew for mentioning it):</h3>
  
  <p>Note with this method I just add an additional <code>target</code> to the dispatcher that creates log files. So you'll insert 2 messages: one in the default <code>storage/logs</code> folder together with all the other requests and one in you custom log folder thus you are still able to use the great Yii2 Debug Toolbar and you can ask clients to hand over their plugin related logs to see what's going on</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-06-19T03:01:05.660Z
Answers.Text: Hi Robin. Thanks for this. I must be missing something - I add the static log function in the main plugin file, then in init() I add the new log location to the dispatcher (and it shows up in the dispatcher targets array) but then calling it with (in my case) NewsletterSignup::log(); results in it being written to the web log only... not the new plugin log. Is there something missing from your static log method? It doesn't look like it does anything other than write to the Craft log? Thanks in advance!
Answers.UserDisplayName: JamesNZ
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-06-19T04:53:11.650Z
Answers.Text: What is your file location? Maybe you didn't specify a valid path?
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-06-19T22:56:12.147Z
Answers.Text: Hi Robin. The file location is the same as the example, which maps to /Users/me/Projects/project-name/src/plugins/newslettersignup/src/NewsletterSignup.log. I tried creating the file and setting it to 777 just to rule out permissions. Didn't make a difference. The path is definitely correct and points to a file (despite me having had created it). Thanks.
Answers.UserDisplayName: JamesNZ
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-08-21T14:22:43.610Z
Answers.Text: Rather than writing to your plugin's directory you can write to Craft's storage directory:
  
  `'logFile' => Craft::getAlias('@storage/logs/pluginhandle.log'),`
Answers.UserDisplayName: John D Wells
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-07-22T15:49:18.327Z
Answers.Text: I published a refinement of this technique here in the [Zen and the Art of Craft CMS Log File Reading](https://nystudio107.com/blog/creating-a-custom-logger-for-craft-cms#custom-plugin-module-logging-behavior) article
Answers.UserDisplayName: andrew.welch
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-04-01T21:46:07.350Z
Answers.Text: Niiiiice. A PR for this would be awesome. There are support cases where asking the user to send you just your plugin's log file would be very useful.
Answers.UserDisplayName: andrew.welch
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-04-01T09:31:07.517Z
Answers.LastActivityDate: 2018-04-01T16:49:36.380Z
Answers.LastEditDate: 2018-04-01T16:49:36.380Z
Answers.UserDisplayName: Robin Schambach
Body: <p>In Craft 2, it was possible to have your plugin log to a separate file. For example, it would record items to a <code>myplugin.log</code> file. You would simply be able to do it like this...</p>
  
  <pre class="lang-php prettyprint-override"><code>MyPlugin::log('Lorem ipsum');
  </code></pre>
  
  <p>However, I can't seem to figure out how this would be done in Craft 3. I've seen <a href="https://craftcms.stackexchange.com/a/24082/45">this answer</a>, which demonstrates how to log items in Craft 3 in general. But that just dumps items into the shared <code>web.log</code> file.</p>
  
  <p><strong>How can I log items to <code>myplugin.log</code> in Craft 3?</strong></p>
  
Tags: <plugin-development><craft3><logs>
Title: Craft 3 plugins - Logging in a separate *.log file
ThreadText: # Craft 3 plugins - Logging in a separate *.log file
  
  (Asked by: username_0 on 2018-04-01)
  
  In Craft 2, it was possible to have your plugin log to a separate file. For example, it would record items to a `myplugin.log` file. You would simply be able to do it like this...
  
  ```php
  MyPlugin::log('Lorem ipsum');
  
  ```
  
  However, I can't seem to figure out how this would be done in Craft 3. I've seen [this answer](https://craftcms.stackexchange.com/a/24082/45), which demonstrates how to log items in Craft 3 in general. But that just dumps items into the shared `web.log` file.
  
  **How can I log items to `myplugin.log` in Craft 3?**
  
  **Tags:** plugin-development, craft3, logs
  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_4 on 2018-04-01. Score: 10 | Accepted answer
  
  ### Edit 2
  
  I came up with a far far far better approach after a little brainstorming. I'll keep my old answer here but you should probably just use the first snipped.
  
  In your main Pluginfile.php
  
  ```php
  public static function log($message){
      Craft::getLogger()->log($message, \yii\log\Logger::LEVEL_INFO, 'your-plugin-handle');
  }
  
  public function init(){
      $fileTarget = new \craft\log\FileTarget([
          'logFile' => __DIR__ . '/pluginName.log', // <--- path of the log file
          'categories' => ['your-plugin-handle'] // <--- categories in the file
      ]);
      // include the new target file target to the dispatcher
      Craft::getLogger()->dispatcher->targets[] = $fileTarget;
      ....
  }
  
  ```
  
  Explanation: `categories` is an array of all categories that should be in the log file. You usually want to allow only categories of your own plugin (you have to use an unique identifier in case certain other developers try to add the same category). Whenever you want to log something with the Craft/Yii `log` method that match one of your given categories in the array it will be logged in your file as well.
  
  ### Old answer
  
  Create this file somewhere in your plugin
  
  ### FileTarget
  
  ```php
  class FileTarget extends \yii\log\FileTarget{
  
      // an array of categories that should be logged
      // note: your target receives all `Yii::log()` messages
      // but you can filter them with this array
      // if you want to track all messages of type 'application' as well
      // just include it in the array
      public $categories = ['a-category-that-you-would-like-to-log']; //<- usually your plugin handle or something
  
      // set the file path
      public function setLogFile($path = __DIR__){
          // I'm lazy so I just use the current location since it's in my 'src/' folder anyway 
          // you can use Crafts default folders or whatever you like
          $this->logFile = $path . '/test.log';
          return $this;
      }
  
      // Optional -> a callback that formats your messages
      // remove this function if there is
      // no formatting needed or if you want to use the default
      public function formatMessage($message)
      {
          list($text, $level, $category, $timestamp) = $message;
          $level = 'Your fancy plugin Name';
  
          if ($category == 'a-category-that-you-would-like-to-log') {
              return date('Y-m-d H:i:s', $timestamp) . " [$level][$category] $text";
          }
      }
  }
  
  ```
  
  ### In your Plugin main file
  
  ```php
  public static $_fileTarget;
  
  public static function log($message){
      if(self::$_fileTarget === null){
          /** @var FileTarget _fileTarget */
          self::$_fileTarget = Craft::createObject('namespace\pluginhandle\filetarget');
          // set the path
          self::$_fileTarget->setLogFile();
          // include your target to the current dispatcher targets 
          // -> all messages are tracked in your target as well. 
          Craft::getLogger()->dispatcher->targets[] = self::$_fileTarget;
      }
  
      // just use the default Craft/Yii logging method but with your category
      Craft::getLogger()->log($message, \yii\log\Logger::LEVEL_INFO, 'a-category-that-you-would-like-to-log');
  }
  
  ```
  
  ### Usage
  
  ```php
  Plugin::log('Lorem ipsum');
  Craft::getLogger()->log('Lorem ipsum', \yii\log\Logger::LEVEL_INFO, 'a-category-that-you-would-like-to-log');
  Craft::info('Lorem ipsum', 'a-category-that-you-would-like-to-log');
  
  ```
  
  Maybe we could create a feature/pull request in order to create this feature by default. So every Plugin receives it's own category (by plugin handle) and if these categories are recognized the logger logs them in a separate file
  
  ### Edit (thanks Andrew for mentioning it):
  
  Note with this method I just add an additional `target` to the dispatcher that creates log files. So you'll insert 2 messages: one in the default `storage/logs` folder together with all the other requests and one in you custom log folder thus you are still able to use the great Yii2 Debug Toolbar and you can ask clients to hand over their plugin related logs to see what's going on
  
  > **Comments:**
  > **username_2**: Niiiiice. A PR for this would be awesome. There are support cases where asking the user to send you just your plugin's log file would be very useful.  
  > **username_5**: Hi username_4. Thanks for this. I must be missing something - I add the static log function in the main plugin file, then in init() I add the new log location to the dispatcher (and it shows up in the dispatcher targets array) but then calling it with (in my case) NewsletterSignup::log(); results in it being written to the web log only... not the new plugin log. Is there something missing from your static log method? It doesn't look like it does anything other than write to the Craft log? Thanks in advance!  
  > **username_4**: What is your file location? Maybe you didn't specify a valid path?  
  > **username_5**: Hi username_4. The file location is the same as the example, which maps to /Users/me/Projects/project-name/src/plugins/newslettersignup/src/NewsletterSignup.log. I tried creating the file and setting it to 777 just to rule out permissions. Didn't make a difference. The path is definitely correct and points to a file (despite me having had created it). Thanks.  
  > **username_6**: Rather than writing to your plugin's directory you can write to Craft's storage directory:  `'logFile' => Craft::getAlias('@storage/logs/pluginhandle.log'),`  
  > **username_2**: I published a refinement of this technique here in the [Zen and the Art of Craft CMS Log File Reading](https://nystudio107.com/blog/creating-a-custom-logger-for-craft-cms#custom-plugin-module-logging-behavior) article  
  
  ---
  
  ### Answer by username_1 on 2018-10-05. Score: 9
  
  Another perhaps simpler approach is to write to your own log file without using the Craft logger at all.
  
  ```
  $file = Craft::getAlias('@storage/logs/pluginhandle.log');
  $log = date('Y-m-d H:i:s').' '.$message."\n";
  
  \craft\helpers\FileHelper::writeToFile($file, $log, ['append' => true]);
  
  ```
  
  UPDATE:
  
  This logic has been put into a helper class for modules and plugins in Craft CMS:
  <https://github.com/putyourlightson/craft-log-to-file>
  
  > **Comments:**
  > **username_0**: That's pretty slick! Just circumvent the whole system.  
  > **username_2**: Just remember, there's a reason why Yii2's logging system jumps through the hoops that it does.  
  > **username_3**: Thank you for this Ben!  
  > **username_1**: Sure thing Anna, I now use this approach for all plugins with this helper class: https://github.com/putyourlightson/craft-log-to-file  
  
  ---
  
  ### Answer by username_2 on 2020-02-12. Score: 2
  
  Adding this for posterity, for any future-traveller who happens to come along.
  
  Here's everything you need to know about making a custom logger for Craft CMS:
  
  [Creating a Custom Logger for Craft CMS](https://nystudio107.com/blog/creating-a-custom-logger-for-craft-cms)
  
  And then once you have a log file, you need to know how to read it:
  
  [Zen and the Art of Craft CMS Log File Reading](https://nystudio107.com/blog/zen-and-the-art-of-craft-cms-log-file-reading)
  
  Godspeed, future traveller!
  
  
  ---
  
  